2010-06-24 3 views
20

Je suis assez nouveau à F # et est venu par la fonction Seq.sortBy mais il est en train de trier ma liste dans l'ordre croissant. Comment l'obtenir pour trier dans l'ordre décroissant en utilisant le Seq.sort?F # Seq.sortBy dans l'ordre décroissant

Par exemple, un exemple de code serait ...

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

me donne une sortie de 1 2 3 4 5 6 7 8 9 10, quand je veux vraiment le faire de 10 à 1.

Répondre

20

En regardant les autres réponses, méfiez-vous unaire moins et 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|] 

Je pense que vous voulez réellement-x-moins-négatif :

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

pour un enveloppement autour du type entier qui s'étend sur -2^N..2^N-1.

+2

Brian, J'espère que cela ne vous dérange pas, mais j'ai ajouté des commentaires montrant la sortie. – gradbot

+0

super, merci ... – Brian

+1

Juste comme une note-'-x-1 = ~~~ x' parce que -x = ~~~ x + 1'. Voir [Complément à deux] (https://en.wikipedia.org/wiki/Two%27s_complement). Vous pouvez donc raccourcir '(fun x -> -x - 1)' simplement '(~~~)' si vous le souhaitez. – FooBarTheLittle

6

Vous pouvez résoudre ce problème en fournissant une clé négative

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

en outre, il est un peu plus facile (et le type plus sûr) d'utiliser les fonctions printf pour l'affichage du texte en F #. Par exemple

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

Merci pour les exemples –

+0

clé négative n'aide pas ou ne fonctionne pas pour 'DateTime' malheureusement – Maslow

18

encore plus court:

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

C'est un truc sympa – JaredPar

5

Si vous le savez, à l'avance, que vous aurez une séquence relativement faible, je pense que cela est plus facile à lire ...

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

Bien sûr, ce ne est pas conseillé si vous avez un séquence potentiellement très grande.

15

Tout d'abord, étendons Seq avec une fonction sortWith même que List et Array ont.

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

Ensuite, nous allons étendre Operators avec une fonction flip souvent utile.

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

Maintenant, nous pouvons tirer parti de la fonction compare générique générique (vous pouvez l'utiliser avec une séquence d'éléments comparables) et la sécurité (en ce qui concerne l'observation de Brian) sorte de séquence inverse.

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

Merci pour la suggestion. Je vous donne +1 pour l'exemple de l'extension –

8

Une autre option consiste à envelopper 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

vous avez une faute de frappe: il devrait être Seq.sortByDesc (fun x -> x). mais en fait, vous pouvez simplement utiliser la fonction 'id': Seq.sortByDesc id –

+0

Fixe, merci. J'ai juste utilisé ce que Mark utilisait pour la cohérence, mais ouais 'id' est bon à savoir. – dahlbyk

+0

Merci pour l'exemple –

4

Solutions qui utilisent moins unaire: (fun x -> -x - 1) et (fun x -> -x) ne fonctionnent pas lorsque vous avez des types non signés:

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 '~-' 

lieu nous pouvons utiliser le fait que -x = ~~~x + 1~~~ est ab opérateur de négation de sens et ainsi -x - 1 = ~~~x.Ainsi, la solution à court qui fonctionne pour les deux types signés et non signés:

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

Exemples:

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|]