2015-11-30 63 views
3

我有以下的短代码,只计算一个文本的话: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) 

排序函数首先通过分选发生的次数,然后按字母顺序的话,这两个下降。我需要按事件降序,然后按字母顺序升序。

用LINQ很容易用OrderByDescendingThenBy。我如何在F#中获得相同的结果而不重复使用LINQ?

谢谢。

+2

你可以使用LINQ的方法,就像你在C# – Carsten

+4

的方式将:只是改变你的代码到'Seq.sortBy(fun(w,ln) - >(-ln,w))'应该可以很好地工作 – Carsten

+1

作为快速回答:发生次数否定的Seq.sortBy,按字母顺序排列的单词:':> Seq.sortBy(fun(w,ln) - >(-ln,w))'。 –

回答

7

您可以使用sortBy代替,使消极出现的次数:

|> Seq.sortBy (fun (w, ln) -> (-ln, w)) 

另外,如果你遇到了更复杂的情况下,你可以使用它采用了比较器的功能功能sortWith

|> Seq.sortWith (fun (w1, ln1) (w2, ln2) -> compare (ln2, w1) (ln1, w2)) 

事实上,第一种解决方案是针对您的特定情况的捷径,因为您可以将数字设为负数,但如果您有更多字段而不是数字,那么通过使用sortWith您可以实现相同与Linq中的OrderBy ... ThenBy一样,通过对元组进行排序并在元素下降时交换元素。

请注意,两种替代方法都依赖structural comparison而不是元组。

+0

因此......在排序不是整数但只是一些字符串的假设情况下,我不得不求助于sortWith方法吗? –

+1

也许是的,特别是如果你想要一次性将这些字符串升序和降序排序。 – Gustavo

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) 
相关问题