2010-06-25 2 views
0

J'ai une liste de mots et je veux trouver combien de fois ils se produisent dans un fichier .txt. La liste de mots est quelque chose comme ce qui suit:Comment compter le nombre d'occurrences d'une liste d'éléments dans un autre fichier .txt?

wordlist = ['cup', 'bike', 'run'] 

Je veux être en mesure non seulement de ramasser ces mots, mais aussi des choses comme CUP, cycliste, course, tasses, etc. Je pense que je besoin d'un régulier expression. Voici ce que je pensais mais cela ne fonctionne pas:

len(re.findall(wordlist, filename, re.I)) 

Merci d'avance!

Répondre

2

Vous êtes proche. Mais re.findall prend un motif et une chaîne, pas une liste de mots et un nom de fichier. Mais, si vous lisez votre fichier dans une chaîne et transformez votre liste de mots en un modèle, alors vous l'obtiendrez.

Le motif dont vous avez besoin ressemblera à ceci: r"cup|bike|run". Vous pouvez faire "|".join(wordlist) pour obtenir ceci.

C'est une manière très approximative de compter toutes ces instances. Notez que si votre fichier contient les mots "Ma matraque a été scuppée", alors re.findall trouvera "run" et "cup" dans les mots plus gros. Donc, vous pouvez vouloir modifier votre modèle pour attraper les débuts et les fins des mots.

Pour obtenir des mots entiers uniquement, utilisez ce modèle: r"\b(cup|bike|run)\b". Bien sûr, vous devrez remplir toutes les variétés de mots que vous recherchez.

+1

Même en ajoutant le début et la fin de l'ajustement des mots, il y aura toujours des mots qui ne devaient pas être trouvés (par exemple "hiccup", "runt", etc.). Peut-être en utilisant WordNet ou quelque chose d'autre dictionnaire pour trouver toutes les différentes formes d'un mot, puis utilisez les limites de mots des deux côtés des termes de recherche ... – tgray

+0

Merci, @tgray. J'ai peaufiné ma réponse pour inclure un motif pour faire correspondre des mots entiers. – eksortso

+1

Merci eksortso! Je n'ai pas compris la différenciation modèle/chaîne et maintenant je le vois. La liste de mots que j'utilise actuellement est composée de mots plus longs, donc je ne devrais pas tomber sur les problèmes étranges qui surviennent avec cup and run, mais je penserai certainement plus à utiliser des mots entiers seulement. Merci! – dandyjuan

2

Les besoins regex travailler, mais cela devrait vous aider à démarrer:

from __future__ import with_statement # only if < 2.6 
from collections import defaultdict 
import re 

matches = defaultdict(int) 
with open(filename) as f: 
    for mtch in re.findall(r'\b(cup|bike|run)', f.read(), re.I): 
     matches[mtch.lower()] += 1 
+0

Il n'est pas clair si vous faites est nécessaire. Ce que vous résolvez est "combien de fois * chaque * mot se produit" quand OP a dit "combien de fois ils se produisent" - il ne me semble pas nécessaire de compter individuellement. Aussi vérifier que le début de \ b mot est ennuyeux - il va "trouver" * cup * dans * cupid *, * run * dans * run *, * meat * in * meatless * et ainsi de suite –

1

Vous devez d'abord deviner toutes les formes des mots et qui semble un PITA. Mais voici une fn simplifiée je l'ai écrit après avoir lu http://www.theenglishspace.com/spelling/:

def getWordForms(word): 
    ''' Given an English word, return list of possible forms 
    ''' 
    l = [word] 
    if len(word)>1: 
     l.extend([word + 's', word + 'ing', word + 'ed']) 
     wor, d = word[:-1], word[-1:] 
     if d == 'e': 
      l.append(word + 'd') 
      l.append(wor + 'ing') 
      if wor[-1:] == 'f': 
       l.append(wor[:-1] + 'ves') 
     elif d == 'y': 
      l.append(wor + 'ied') 
      l.append(wor + 'ies') 
     elif d == 'z': 
      l.append(word + 'zes') # double Z 
     elif d == 'f': 
      l.append(wor + 'ves') 
     elif d in 'shox': 
      l.append(word + 'es') 
     if re.match('[^aeiou][aeiou][^aeiou]', word): 
      l.append(word + d + 'ing') # double consonant 
      l.append(word + d + 'ed') 
    return l 

Il est trop généreux dans les variantes de mots, il devine - mais qui est bien parce que ce n'est pas un correcteur orthographique et vous allez utiliser \ b pour les limites des mots des deux côtés.

Questions connexes