2015-11-30 64 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) 
相關問題