Ich möchte beispielsweise die 10 häufigsten Wörter in einer Textdatei finden. Erstens sollte die Lösung für Tastenanschläge optimiert werden (mit anderen Worten - meine Zeit). Zweitens für die Leistung. Folgendes muss ich bisher für die Top 10 tun:
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
Ich könnte ein Java-, Python- usw. Programm erstellen, in dem ich (word, numberOfOccurences) in einem Wörterbuch speichere und den Wert sortiere, oder ich könnte MapReduce verwenden, aber ich optimiere für Tastenanschläge.
Gibt es falsche Positive? Gibt es einen besseren Weg?
command-line
shell-script
Lukasz Madon
quelle
quelle
Antworten:
Das ist so ziemlich die gebräuchlichste Methode, "N gebräuchlichste Dinge" zu finden, mit der Ausnahme, dass Sie eine verpassen
sort
und eine unentgeltliche habencat
:Wenn Sie kein
sort
vor demuniq -c
eingeben, werden Sie wahrscheinlich eine Menge falscher Singleton-Wörter erhalten.uniq
Nur eindeutige Linienfolgen, keine allgemeine Einheitlichkeit.EDIT: Ich habe einen Trick vergessen, "Worte anhalten". Wenn Sie sich englischen Text ansehen (sorry, hier einsprachig nordamerikanisch), nehmen Wörter wie "von", "und" die "fast immer die ersten zwei oder drei Plätze ein. Sie wollen sie wahrscheinlich beseitigen. In der GNU Groff-Distribution befindet sich eine Datei mit dem Namen
eign
, die eine anständige Liste von Stoppwörtern enthält. Meine Arch Distribution hat/usr/share/groff/current/eign
, aber ich glaube ich habe auch alte Unixe gesehen/usr/share/dict/eign
oder/usr/dict/eign
in.Sie können Stoppwörter wie diese verwenden:
Ich vermute, dass die meisten menschlichen Sprachen ähnliche "Stoppwörter" benötigen, die aus den aussagekräftigen Worthäufigkeitszählungen entfernt wurden, aber ich weiß nicht, wo ich vorschlagen soll, Stoppwörterlisten für andere Sprachen zu erhalten.
BEARBEITEN:
fgrep
sollte den-w
Befehl verwenden, der die Ganzwortübereinstimmung ermöglicht. Dies vermeidet Fehlalarme bei Wörtern, die nur kurze Stopp-Werke enthalten, wie "a" oder "i".quelle
cat
einen erheblichen Leistungsaufwand hinzu? Ich mag die Pipe-Syntax. Was macht das * in '[\ n *]'?find
Ausgabe suchen möchte ? Das heißt, Wörter/
anstelle von Leerzeichen und Ähnlichem aufteilen .find somewhere optoins | tr '/' '\n' | sort | uniq -c | sort -k1.1nr | head -10
Das funktioniert besser mit utf-8:
quelle
Lass uns AWK benutzen!
Diese Funktion listet die Häufigkeit jedes in der angegebenen Datei vorkommenden Wortes in absteigender Reihenfolge auf:
Sie können es folgendermaßen in Ihrer Datei aufrufen:
und für die Top 10 Wörter:
Quelle: AWK-Station Ruby
quelle
Lass uns Haskell benutzen!
Das wird zu einem Sprachkrieg, nicht wahr?
Verwendung:
Alternative:
quelle
sort | uniq -c | sort -nr
.Text
oder wechselnByteString
, was so einfach ist, als würde man es qualifiziert importieren und den Funktionen das Qualifikationsmerkmal voranstellen.So etwas sollte mit Python funktionieren, das allgemein verfügbar ist:
Dies setzt ein Wort pro Zeile voraus. Wenn es mehr gibt, sollte das Teilen auch einfach sein.
quelle
cat README.md | python -c 'import collections, sys, pprint; pprint.pprint(collections.Counter(sys.stdin));'
Dies ist ein klassisches Problem, das 1986 einige Resonanz fand, als Donald Knuth eine schnelle Lösung mit Hash-Versuchen in einem 8-seitigen Programm implementierte , um seine literarische Programmiertechnik zu veranschaulichen, während Doug McIlroy, der Pate von Unix-Pipes, mit einem antwortete Einzeiler, das war nicht so schnell, hat aber die Arbeit erledigt:
Natürlich hat McIlroys Lösung die Zeitkomplexität O (N log N), wobei N eine Gesamtzahl von Wörtern ist. Es gibt viel schnellere Lösungen. Beispielsweise:
Hier ist eine C ++ - Implementierung mit der oberen zeitlichen Komplexität O ((N + k) log k), typischerweise - nahezu linear.
Im Folgenden finden Sie eine schnelle Python-Implementierung unter Verwendung von Hash-Wörterbüchern und Heap mit Zeitkomplexität O (N + k log Q), wobei Q eine Reihe eindeutiger Wörter ist:
CPU-Zeitvergleich (in Sekunden):
Anmerkungen:
quelle