I have the following short code that simply counts words of a text:
[<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)
The sort function is sorting first by the number of occurrences, and then by the word in alphabetical order, both descending. I need to do it descending by occurrences, but then ascending by alphabetical order.
With LINQ is very easy with OrderByDescending and ThenBy. How I achieve the same result in F# without recurring to LINQ?
Thank you.
You can use sortBy
instead and make negative the number of occurrences:
|> Seq.sortBy (fun (w, ln) -> (-ln, w))
Alternatively, if you run into more complicated cases you can use the function sortWith
which uses a comparer function:
|> Seq.sortWith (fun (w1, ln1) (w2, ln2) -> compare (ln2, w1) (ln1, w2))
In fact the first solution is a short-cut for your specific case because you can make the number negative, but if you have more fields, not numeric, then by using sortWith
you can achieve the same as with OrderBy
... ThenBy
in Linq, by ordering the tuple and swapping the elements when it's descending.
Note that both alternatives rely on structural comparison over tuples.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With