F# - 如何通过降序然后升序对列表进行排序?

时间:2015-11-30 08:00:28

标签: sorting f#

我有以下简短的代码,只需计算文字:

[<EntryPoint>]  
let main argv =   
    let text = File.ReadAllText("gettysburg.txt").ToLower()  
    Regex.Split(text, "\W+")  
    |> Seq.groupBy id  
    |> Seq.map (fun (k, grp) -> (k, grp |> Seq.length))  
    |> Seq.sortByDescending (fun (w, ln) -> (ln, w))  
    |> Seq.iter (fun (k, ln) -> printfn "%s\t%i" k ln)  

排序函数首先按出现次数排序,然后按字母顺序排序,均为降序排序。我需要按出现次数递减,然后按字母顺序递增。

使用 OrderByDescending ThenBy ,LINQ非常简单。如何在不重复使用LINQ的情况下在F#中实现相同的结果?

谢谢。

2 个答案:

答案 0 :(得分:7)

您可以改为使用CommandManager并使出现次数为负数:

sortBy

或者,如果遇到更复杂的情况,可以使用使用比较器函数的函数|> Seq.sortBy (fun (w, ln) -> (-ln, w))

sortWith

事实上,第一个解决方案是针对您的特定情况的快捷方式,因为您可以将数字设为负数,但如果您有更多字段,而不是数字,那么使用|> Seq.sortWith (fun (w1, ln1) (w2, ln2) -> compare (ln2, w1) (ln1, w2)) 可以实现与Linq中的sortWith ... OrderBy,通过排序元组并在元素下降时交换元素。

请注意,两种选择都依赖于structural comparison而不是元组。

答案 1 :(得分:4)

对降序进行排序与​​对负数进行升序排序相同(因为a <= b然后是-b <= -a)所以这应该有效:

[<EntryPoint>]  
let main argv =   
    let text = File.ReadAllText("gettysburg.txt").ToLower()  
    Regex.Split(text, "\W+")  
    |> Seq.groupBy id  
    |> Seq.map (fun (k, grp) -> (k, grp |> Seq.length))  
    |> Seq.sortBy (fun (w, ln) -> (-ln, w))  
    |> Seq.iter (fun (k, ln) -> printfn "%s\t%i" k ln)