2010-06-24 30 views
20

Ich bin ziemlich neu in F # und kam durch die Seq.sortBy Funktion, aber es ist meine Liste in aufsteigender Reihenfolge sortieren. Wie bekomme ich es in absteigender Reihenfolge mit dem Seq.sort zu sortieren?F # Seq.sortBy in absteigender Reihenfolge

Zum Beispiel wäre ein Beispiel-Code ... sein

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

gibt mir eine Leistung von 1 2 3 4 5 6 7 8 9 10, wenn ich es wirklich will es 10-1 tun.

Antwort

20

bei den anderen Antworten suchen, passen einstellige minus und 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|] 

Ich glaube, Sie tatsächlich negativ-x-Minus-Eins wollen :

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

für einen Umschlag um Integer-Typ, der -2^N..2^N-1 überspannt.

+2

Brian, ich hoffe, es macht Ihnen nichts aus, aber ich habe Kommentare hinzugefügt, die die Ausgabe zeigen. – gradbot

+0

toll, danke ... – Brian

+1

Nur als Nebenzeichen '-x-1 = ~~~ x' weil' -x = ~~~ x + 1'. Siehe [Zweierkomplement] (https://en.wikipedia.org/wiki/Two%27s_complement). Sie können also '(fun x -> -x - 1)' auf einfach '(~~~)' verkürzen, wenn Sie möchten. – FooBarTheLittle

6

Sie können dieses Problem beheben, indem eine negativen Schlüssel

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

auch ein bisschen einfacher es ist (und geben Sie sicherer) für die Anzeige von Text in F # die printf Funktionen zu nutzen. Zum Beispiel

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

Danke für die Beispiele –

+0

negativer Schlüssel hilft oder arbeitet nicht für 'DateTime' leider – Maslow

18

Noch kürzere:

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

Das ist ein netter Trick – JaredPar

5

Wenn Sie wissen, vor der Zeit, dass Sie eine relativ kleine Sequenz haben werden, ich denke, das ist besser lesbar ...

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

Natürlich, es ist nicht ratsam, wenn Sie ein bekam möglicherweise sehr große Sequenz.

15

Zuerst erweitern wir Seq mit einer sortWith Funktion wie List und Array haben.

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

Als nächstes wollen wir Operators mit einer oft nützlich flip Funktion erweitern.

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

Jetzt können wir die allgemeine compare Funktion nutzen zu generisch und sicher (in Bezug auf Brians Beobachtung) umgekehrte Reihenfolge sortieren (Sie dies mit jeder Folge von vergleichbaren Elementen verwenden können).

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

Danke für den Vorschlag. Ich gebe Ihnen +1 für das Beispiel der Erweiterung –

8

Eine weitere Option ist System.Linq.Enumerable.OrderByDescending() einzuwickeln:

// #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

Sie haben einen Tippfehler: Es sollte Seq.sortByDesc sein (Spaß x -> x). aber eigentlich können Sie einfach die 'ID' Funktion verwenden: Seq.sortByDesc id –

+0

Fest, danke. Ich habe nur das verwendet, was Mark aus Gründen der Konsistenz verwendet hat, aber "id" ist gut zu wissen. – dahlbyk

+0

Danke für das Beispiel –

4

Lösungen, die einstellige minus verwenden: (fun x -> -x - 1) und (fun x -> -x) nicht funktionieren, wenn Sie nicht signierte Typen haben:

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

Statt wir können die Tatsache verwenden, dass -x = ~~~x + 1~~~ ist ab itwise negation operator und somit -x - 1 = ~~~x.So die kurze Lösung, die für beide mit und ohne Vorzeichen Arten funktioniert:

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

Beispiele:

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