2010-06-24 15 views
20

Soy bastante nuevo en F # y obtuve la función Seq.sortBy, pero está ordenando mi lista en orden ascendente. ¿Cómo puedo ordenarlo en orden descendente usando Seq.sort?F # Seq.sortPor orden descendente

Por ejemplo un código de ejemplo sería ...

let DisplayList = 
seq{0..10} 
|> Seq.sortBy(fun x -> x) 
|> Seq.iter(fun x -> Console.WriteLine(x.ToString())) 

me da una salida de 1 2 3 4 5 6 7 8 9 10, cuando realmente quiero que haga es de 10 a 1.

Respuesta

20

En cuanto a las otras respuestas, tenga cuidado menos unario y el MININT:

let a = [| 1; -1; System.Int32.MinValue; 0; System.Int32.MaxValue; 1 |] 

printfn "%A" (a |> Array.sortBy (fun x -> x)) 
// [|-2147483648; -1; 0; 1; 1; 2147483647|] 

printfn "%A" (a |> Array.sortBy (fun x -> -x)) // uh-oh! 
// [|-2147483648; 2147483647; 1; 1; 0; -1|] 

Creo que realmente desea negativo-x-menos-uno :

printfn "%A" (a |> Array.sortBy (fun x -> -x - 1)) 
// [|2147483647; 1; 1; 0; -1; -2147483648|] 

para una envoltura alrededor del tipo entero que abarca -2^N..2^N-1.

+2

Brian, espero que no te importe, pero he agregado comentarios que muestran el resultado. – gradbot

+0

genial, gracias ... – Brian

+1

Solo como una nota al margen '-x-1 = ~~~ x' porque' -x = ~~~ x + 1'. Ver [Complemento de dos] (https://en.wikipedia.org/wiki/Two%27s_complement). Así que puedes acortar '(diversión x -> -x - 1)' a simplemente '(~~~)' si quieres. – FooBarTheLittle

6

Puedes solucionar este problema proporcionando una clave negativa

let DisplayList = 
    seq { 0..10 } 
    |> Seq.sortBy (fun x -> -x) 
    |> Seq.iter (fun x -> Console.WriteLine(x.ToString())) 

también que es un poco más fácil (y más seguro escribir) para utilizar las funciones printf para la visualización de texto en C#. Por ejemplo

let DisplayList = 
    seq { 0..10 } 
    |> Seq.sortBy (fun x -> -x) 
    |> Seq.iter (printfn "%d") 
+0

Gracias por los ejemplos –

+0

clave negativa no ayuda o funciona para 'DateTime' desafortunadamente – Maslow

18

aún más corto:

seq { 0..10 } 
    |> Seq.sortBy (~-) // Unary minus 
    |> Seq.iter (printfn "%d") 
+2

Eso es un buen truco – JaredPar

5

Si usted sabe, de antemano, que tendrá una secuencia relativamente pequeña, creo que esto es más fácil de leer ...

let x = seq { 0.. 10 } |> Seq.toArray |> Array.rev

Por supuesto, no es recomendable si usted tiene una secuencia potencialmente muy grande.

15

En primer lugar, vamos a extender Seq con una función sortWith igual que la lista y la matriz tienen.

namespace Microsoft.FSharp.Collections 
module Seq = 
    let sortWith f e = 
     let e' = e |> Seq.toArray 
     e' |> Array.sortInPlaceWith f 
     e' |> Seq.readonly 

continuación, vamos a extender Operators con una función de frecuencia útil flip.

namespace Microsoft.FSharp.Core 
module Operators = 
    let flip f x y = f y x 

Ahora, podemos aprovechar la función genérica compare por medicamentos genéricos (se puede usar esto con cualquier secuencia de elementos comparables) y seguro (en lo que se refiere a la observación de Brian) secuencia inversa tipo.

{0..10} 
|> Seq.sortWith (flip compare) 
|> Seq.iter (printfn "%A") 
+0

Gracias por la sugerencia. Te doy +1 para el ejemplo de extender –

8

Otra opción es envolver System.Linq.Enumerable.OrderByDescending():

// #r "System.Core" 
module Seq = 
    let sortByDesc f s = Enumerable.OrderByDescending(s, new Func<'a, 'b>(f)) 

{0..10} |> Seq.sortByDesc (fun x -> x) 
+0

tienes un error tipográfico: debe ser Seq.sortByDesc (diversión x -> x). pero en realidad, solo puede usar la función 'id': Seq.sortByDesc id –

+0

Solucionado, gracias. Acabo de utilizar lo que Mark usó para coherencia, pero sí 'id' es bueno saberlo. – dahlbyk

+0

Gracias por el ejemplo –

4

soluciones que utilizan menos unario: (fun x -> -x - 1) y (fun x -> -x) no funcionan cuando usted tiene los tipos sin signo:

let a = [| 0uy; 255uy; 254uy; 1uy |] 
printfn "%A" (a |> Array.sortBy (fun x -> -x - 1)) 
// error FS0001: The type 'byte' does not support the operator '~-' 

lugar podemos usar el hecho de que -x = ~~~x + 1 donde ~~~ es ab Operador de negación a lo largo y por lo tanto -x - 1 = ~~~x.Así que la solución a corto que trabaja para y sin signo de dos tipos:

Array.sortBy (~~~) // equivalent to Array.sortBy (fun x -> ~~~x) 

Ejemplos:

let a = [| 0uy; 255uy; 254uy; 1uy |] 
printfn "%A" (a |> Array.sortBy (~~~)) 
// [|255uy; 254uy; 1uy; 0uy|] 
let a = [| 1; -1; System.Int32.MinValue; 0; System.Int32.MaxValue; 1 |] 
printfn "%A" (a |> Array.sortBy (~~~)) 
// [|2147483647; 1; 1; 0; -1; -2147483648|] 
Cuestiones relacionadas