2010-06-24 106 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|]