Je veux trouver, disons, 10 mots les plus courants dans un fichier texte. Premièrement, la solution doit être optimisée pour les frappes au clavier (autrement dit, à mon heure). Deuxièmement, pour la performance. Voici ce que j'ai jusqu'à présent pour faire partie du top 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
Je pourrais créer un programme java, python, etc. dans lequel je stockerais (mot, numberOfOccurences) dans un dictionnaire et trierais la valeur, ou je pourrais utiliser MapReduce, mais j'optimisais pour les frappes au clavier.
Y a-t-il des faux positifs? Y a-t-il un meilleur moyen?
command-line
shell-script
Lukasz Madon
la source
la source
Réponses:
C'est à peu près la façon la plus courante de trouver "N choses les plus communes", sauf qu'il vous manque un
sort
, et vous avez un gratuitcat
:Si vous ne le mettez pas
sort
avant,uniq -c
vous obtiendrez probablement beaucoup de faux mots singleton.uniq
ne fait que des longueurs de lignes uniques, pas uniques.EDIT: J'ai oublié un truc, "mots d'arrêt". Si vous regardez le texte anglais (désolé, monolingue nord-américain ici), des mots comme "of", "and", "the" prennent presque toujours les deux ou trois premières places. Vous voulez probablement les éliminer. La distribution GNU Groff a un fichier nommé
eign
qui contient une liste assez décente de mots vides. Ma distribution Arch a/usr/share/groff/current/eign
, mais je pense que j'ai aussi vu/usr/share/dict/eign
ou/usr/dict/eign
dans les anciens Unix.Vous pouvez utiliser des mots vides comme celui-ci:
Mon hypothèse est que la plupart des langues humaines ont besoin de "mots vides" similaires supprimés du nombre de mots significatifs, mais je ne sais pas où suggérer d'obtenir d'autres langues une liste de mots vides.
EDIT:
fgrep
devrait utiliser la-w
commande, qui active la correspondance de mot entier. Cela évite les faux positifs sur les mots qui contiennent uniquement des arrêts brefs, tels que "a" ou "i".la source
cat
il des frais de performance significatifs? J'aime la syntaxe du tuyau. Que fait le * dans '[\ n *]'?find
sortie? Autrement dit, séparez les mots au/
lieu des caractères d'espacement et similaires.find somewhere optoins | tr '/' '\n' | sort | uniq -c | sort -k1.1nr | head -10
Cela fonctionne mieux avec utf-8:
la source
Utilisons AWK!
Cette fonction répertorie la fréquence de chaque mot apparaissant dans le fichier fourni par ordre décroissant:
Vous pouvez l'appeler sur votre fichier comme ceci:
et pour le top 10 des mots:
Source: AWK-ward Ruby
la source
Utilisons Haskell!
Cela se transforme en une guerre de la langue, n'est-ce pas?
Usage:
Alternativement:
la source
sort | uniq -c | sort -nr
.Text
ou à laByteString
place, ce qui est aussi simple que de l'importer qualifié et de préfixer les fonctions avec le qualificateur.Quelque chose comme cela devrait fonctionner avec Python, qui est couramment disponible:
Cela suppose mot par ligne. S'il y en a plus, le fractionnement devrait également être facile.
la source
cat README.md | python -c 'import collections, sys, pprint; pprint.pprint(collections.Counter(sys.stdin));'
C’est un problème classique qui a trouvé un écho en 1986, lorsque Donald Knuth a implémenté une solution rapide avec essais de hachage dans un programme de 8 pages pour illustrer sa technique de programmation, alors que Doug McIlroy, parrain des tubes Unix, répondait par un one-line, ce n’était pas aussi rapide, mais le travail était fait:
Bien entendu, la solution de McIlroy a une complexité temporelle O (N log N), où N est un nombre total de mots. Il existe des solutions beaucoup plus rapides. Par exemple:
Voici une implémentation C ++ avec la complexité temporelle supérieure O ((N + k) log k), généralement - presque linéaire.
Ci-dessous, une implémentation rapide de Python utilisant des dictionnaires de hachage et des tas avec une complexité temporelle O (N + k log Q), où Q est un nombre de mots uniques:
Voici une solution extrêmement rapide dans Rust par Anders Kaseorg.
Comparaison du temps de calcul (en secondes):
Remarques:
la source