2010-06-24 297 views
20

我對F#來說相當新,並且由Seq.sortBy函數提供,但它按升序對我的列表進行排序。如何使用Seq.sort以降序排序?F#Seq.sortBy按降序排列

例如示例代碼將是...

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

給我的1 2 3 4 5 6 7 8 9 10的輸出,當我真的希望它做它從10到1。

回答

20

看着其他的答案,謹防元減號和內政部:

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

我想到你居然要負-X減一:

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

換行大約整數類型,跨越-2^N..2^N-1

+2

Brian,我希望你不介意,但我添加了評論顯示輸出。 – gradbot 2010-06-25 00:58:39

+0

很好,謝謝... – Brian 2010-06-25 01:21:46

+1

就像'-x-1 = ~~~ x'因爲'-x = ~~~ x + 1'。參見[二進制補碼](https://en.wikipedia.org/wiki/Two%27s_complement)。所以,如果你喜歡,你可以簡單地將'(fun x - > -x - 1)'縮短爲'(~~~)'。 – FooBarTheLittle 2016-02-11 10:33:33

6

可以通過提供一個負的關鍵

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

解決這個問題也很簡單一點(和類型安全)使用printf功能在F#顯示文本。例如

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

感謝您的示例 – 2010-06-25 12:08:26

+0

否定鍵不會幫忙或爲'DateTime'工作不幸 – Maslow 2015-12-18 14:43:36

18

更短:

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

這是一個巧妙的把戲 – JaredPar 2010-06-24 15:42:59

5

如果你知道,時間提前,那你就會有一個比較小的順序,我認爲這是更具可讀性...

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

當然,如果你有其不可取可能非常大的序列。

15

首先,讓我們將SeqsortWith函數相同的功能與List和Array一樣。

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

接下來,讓我們擴展Operators與經常有用flip功能。現在

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

,我們可以利用通用compare功能一般(你可以使用這個相媲美元素的任意序列)和安全(關於Brian的觀察)相反的順序排序。

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

感謝您的建議。我給你+1的例子擴展 – 2010-06-25 12:07:22

8

另一種選擇是包裝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

你有一個錯字:它應該是Seq.sortByDesc(fun x - > x)。但實際上,您可以使用'id'功能:Seq.sortByDesc id – 2010-06-25 03:06:07

+0

已修復,謝謝。我只是用馬克用來保持一致性的東西,但是'id'很好理解。 – dahlbyk 2010-06-25 04:25:58

+0

感謝您的示例 – 2010-06-25 12:07:54

4

解決方案使用一元減:

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

相反:(fun x -> -x - 1)(fun x -> -x)當你擁有無符號類型不工作我們可以使用-x = ~~~x + 1其中~~~是ab的事實因此否定運營商,因此-x - 1 = ~~~x。因此,對於這兩種符號和無符號類型作品的簡短的解決方案:

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

例子:

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