Давайте пройдем этот шаг за шагом, создавая функцию для каждого бита:
Преобразование слов, начинающихся с прописных букв, в строчные слова, чтобы все слова были строчными.
Разделить строку на последовательность слов:
let getWords (s: string) =
s.Split(' ')
Превращает "привет мир" в ["hello"; "world"]
Сортировать количество отображаемых слов. Слово в этом смысле представляет собой последовательность символов без пробелов и знаков препинания (! # = И т. Д.)
Часть # 1: отформатировать слово в нижнем регистре без знаков препинания:
let isNotPunctuation c =
not (Char.IsPunctuation(c))
let formatWord (s: string) =
let chars =
s.ToLowerInvariant()
|> Seq.filter isNotPunctuation
|> Seq.toArray
new String(chars)
Включает "Привет!" в "привет".
Часть # 2: Сгруппировать список слов по его форматированной версии.
let groupWords (words: string seq) =
words
|> Seq.groupBy formatWord
Возвращает кортеж, первая часть которого является ключом (formatWord
), вторая часть представляет собой список слов.
Превращает ["hello"; "world"; "hello"]
в
[("hello", ["hello"; "hello"]);
("world", ["world"])]
Сортировка от наиболее часто встречающегося слова и до менее частого.
let sortWords group =
group
|> Seq.sortByDescending (fun g -> Seq.length (snd g))
Сортировка списка по убыванию (по возрастанию) по length
(количеству) элементов во второй части - см. Приведенное выше представление.
Теперь нам просто нужно очистить вывод:
let output group =
group
|> Seq.map fst
Это выбирает первую часть кортежа из группы:
Превращает ("hello", ["hello"; "hello"])
в "привет".
Теперь у нас есть все функции, мы можем соединить их в одну цепочку:
let s = "some long string with some repeated words again and some other words"
let finished =
s
|> getWords
|> groupWords
|> sortWords
|> output
printfn "%A" finished
//seq ["some"; "words"; "long"; "string"; ...]