Я бы сказал, очевидный выбор для решения этой задачи является использование Seq
модуль, который действительно является одним из основных рабочих лошадей в F #. Как сказал Рид, использование словаря не так распространено, так как оно изменено. Последовательности, с другой стороны, являются неизменными. Пример того, как сделать это с помощью последовательности является
let strings = "one, two, one, three, four, one, two, four, five"
let words =
strings.Split([|','|])
|> Array.map (fun s -> s.Trim())
let topTen =
words
|> Seq.groupBy id
|> Seq.map (fun (w, ws) -> (w, Seq.length ws))
|> Seq.sortBy (snd >> (~-))
|> Seq.truncate 10
Я думаю, что код говорит довольно много для себя, хотя, может быть, второй последней строки требует краткого объяснения: snd
-функции дает вторую позицию в паре (т.е. snd (a,b)
- b
), >>
- оператор функциональной композиции (то есть (f >> g) a
- это то же, что и g (f a)
), а ~-
- унарный оператор минус. Обратите внимание, что операторы являются, по существу, функциями, но при использовании (и объявлении) их в качестве функций вы должны обернуть их в круглые скобки. То есть -3
совпадает с (~-) 3
, где в последнем случае мы использовали оператор как функцию.
Всего, что делает вторая последняя строка, сортирует последовательность по отрицательному значению второй записи в паре (количество вхождений).
спасибо, Рид. У меня есть следующий вопрос: в чем разница между Seq.take и Seq.truncate? Когда я должен использовать их каждый? –
@MY_G Seq.take не удастся, если в коллекции будет меньше 10 элементов - усечение всегда будет успешным. (В приведенном выше примере seq.take не удался, так как у меня не было> 10 элементов;)) –