найти n наиболее часто встречающихся слов в файле

найти n наиболее часто встречающихся слов в файле

Я хочу найти, скажем, 10 самых распространенных слов в текстовом файле. Во-первых, решение должно быть оптимизировано для нажатий клавиш (другими словами - моего времени). Во-вторых, для производительности. Вот что у меня есть на данный момент для получения топ-10:

cat test.txt | tr -c '[:alnum:]' '[\n*]' | uniq -c | sort -nr | head  -10
  6 k
  2 g
  2 e
  2 a
  1 r
  1 k22
  1 k
  1 f
  1 eeeeeeeeeeeeeeeeeeeee
  1 d

Я мог бы создать программу на Java, Python и т. д., в которой я бы сохранял (word, numberOfOccurences) в словаре и сортировал бы значения, или я мог бы использовать MapReduce, но я бы оптимизировал нажатия клавиш.

Есть ли ложные срабатывания? Есть ли лучший способ?

решение1

Это, по сути, самый распространенный способ найти «N самых распространенных вещей», за исключением того, что вы пропустили sort, и у вас есть бесполезный cat:

tr -c '[:alnum:]' '[\n*]' < test.txt | sort | uniq -ci | sort -nr | head  -10

Если вы не поставите sortперед , то, uniq -ci скорее всего, получите много ложных одиночных слов. uniqпроверяет только уникальные серии строк, а не общую уникальность.

Вы можете использовать трюк, «стоп-слова». Если вы смотрите на английский текст (извините, здесь одноязычный североамериканский), такие слова, как «of», «and», «the» почти всегда занимают первые два-три места. Вероятно, вы захотите их исключить. В дистрибутиве GNU Groff есть файл с именем, eignкоторый содержит довольно приличный список стоп-слов. В моем дистрибутиве Arch есть /usr/share/groff/current/eign, но я думаю, что я также видел /usr/share/dict/eignили /usr/dict/eignв старых Unix.

Вы можете использовать такие стоп-слова:

tr -c '[:alnum:]' '[\n*]' < test.txt |
fgrep -v -w -f -i /usr/share/groff/current/eign |
sort | uniq -ci | sort -nr | head  -10

Я предполагаю, что большинству человеческих языков необходимо удалить подобные «стоп-слова» из подсчетов частоты употребления значимых слов, но я не знаю, где можно порекомендовать получить списки стоп-слов для других языков.

Флаг -won fgrepвключает сопоставление целых слов. Это позволяет избежать ложных срабатываний для слов, которые просто содержат короткие остановки, например, "a" или "i". Флаг -ion uniqи fgrepигнорирует регистр при сравнении слов.

решение2

Это лучше работает с utf-8:

$ sed -e 's/\s/\n/g' < test.txt | sort | uniq -c | sort -nr | head  -10

решение3

Давайте использовать AWK!

Эта функция выводит список частотности каждого слова, встречающегося в предоставленном файле, в порядке убывания:

function wordfrequency() {
  awk '
     BEGIN { FS="[^a-zA-Z]+" } {
         for (i=1; i<=NF; i++) {
             word = tolower($i)
             words[word]++
         }
     }
     END {
         for (w in words)
              printf("%3d %s\n", words[w], w)
     } ' | sort -rn
}

Вы можете вызвать его в своем файле следующим образом:

$ cat your_file.txt | wordfrequency

и для 10 лучших слов:

$ cat your_file.txt | wordfrequency | head -10

Источник:Руби, принадлежащий AWK

решение4

Давайте использовать Haskell!

Это превращается в языковую войну, не так ли?

import Data.List
import Data.Ord

main = interact $ (=<<) (\x -> show (length x) ++ " - " ++ head x ++ "\n")
                . sortBy (flip $ comparing length)
                . group . sort
                . words

Использование:

cat input | wordfreq

Альтернативно:

cat input | wordfreq | head -10

Связанный контент