F# 按降序排序

F# 按降序排序,f#,F#,我对F#还比较陌生,使用了Seq.sortBy函数,但它是按升序对列表排序的。如何使用Seq.sort按降序排序 例如,一个示例代码是 let DisplayList = seq{0..10} |> Seq.sortBy(fun x -> x) |> Seq.iter(fun x -> Console.WriteLine(x.ToString())) 当我真的希望它从10到1执行时,给我一个1 2 3 4 5 6 7 8 9 10的输出。您可以通过提供一个负键来修复此问

我对F#还比较陌生,使用了Seq.sortBy函数,但它是按升序对列表排序的。如何使用Seq.sort按降序排序

例如,一个示例代码是

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

当我真的希望它从10到1执行时,给我一个1 2 3 4 5 6 7 8 9 10的输出。

您可以通过提供一个负键来修复此问题

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")
甚至更短:

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

看看其他答案,注意一元负号和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|]
我想你实际上想要负x-负1:

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

对于跨越
-2^N..2^N-1

的环绕整数类型,如果您提前知道将有一个相对较小的序列,我认为这更具可读性

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


当然,如果您有一个可能非常大的序列,则不建议这样做。

首先,让我们使用与List和Array相同的
sortWith
函数扩展
Seq

namespace Microsoft.FSharp.Collections
module Seq =
    let sortWith f e = 
        let e' = e |> Seq.toArray
        e' |> Array.sortInPlaceWith f
        e' |> Seq.readonly
接下来,让我们使用一个常用的
翻转
函数扩展
操作符

namespace Microsoft.FSharp.Core
module Operators =
    let flip f x y = f y x
现在,我们可以利用generic
compare
函数进行generic(您可以将其用于任何可比较元素的序列)和safe(根据Brian的观察)反向序列排序

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

另一个选项是包装
System.Linq.Enumerable.OrderByDescending()

/#r“System.Core”
模块序号=
设sortByDesc f s=Enumerable.OrderByDescending(s,new Func(f))
{0..10}|>Seq.sortByDesc(乐趣x->x)

使用一元减号的解决方案:
(fun x->-x-1)
(fun x->-x)
在具有未签名类型时不起作用:

a=[|0uy;255uy;254uy;1uy]
printfn“%A”(A |>Array.sortBy(fun x->x-1))
//错误FS0001:类型“byte”不支持运算符“~-”
相反,我们可以使用这样一个事实:
-x=~~~x+1
,其中
~~
是一个位求反运算符,因此
-x-1=~~x
。因此,适用于有符号和无符号类型的简短解决方案是:

Array.sortBy(~~~)//相当于Array.sortBy(fun x->~~~x)
示例:

a=[|0uy;255uy;254uy;1uy]
printfn“%A”(A |>Array.sortBy(~~~)
//[255uy;254uy;1uy;0uy]
设a=[|1;-1;System.Int32.MinValue;0;System.Int32.MaxValue;1 |]
printfn“%A”(A |>Array.sortBy(~~~)
// [|2147483647; 1; 1; 0; -1; -2147483648|]
F#4.0(Visual Studio 2015)引入了
Seq.sortDescending
Seq.sortDescending

let DisplayList =
    seq { 0..10 }
    |> Seq.sortDescending         ' or |> Seq.sortByDescending id
    |> Seq.iter Console.WriteLine

请参见和

Brian,我希望您不介意,但我添加了显示输出的注释。正如旁注
-x-1=~~~x
,因为
-x=~~~x+1
。看见因此,如果您愿意,可以将
(fun x->-x-1)
缩短为简单的
(~~~)
。但实际上,您可以使用'id'函数:Seq.sortByDesc idFixed,谢谢。我只是使用了Mark用于一致性的方法,但是很高兴知道,
id
。我有一个库,可以为大多数linq链接方法实现这一点。谢谢你的建议。我给你+1作为扩展的例子。很遗憾,负键对
DateTime
无效
let DisplayList =
    seq { 0..10 }
    |> Seq.sortDescending         ' or |> Seq.sortByDescending id
    |> Seq.iter Console.WriteLine