2011-11-28 2 views
3

J'utilise python pour convertir les mots d'une phrase dans un fichier texte en jetons individuels dans une liste dans le but de compter des fréquences de mots. J'ai des problèmes pour convertir les différentes phrases en une seule liste. Voici ce que je fais:Conversion de phrases dans un fichier en jetons de mots dans une liste

f = open('music.txt', 'r') 
sent = [word.lower().split() for word in f] 

Cela me donne la liste suivante:

[['party', 'rock', 'is', 'in', 'the', 'house', 'tonight'], 
['everybody', 'just', 'have', 'a', 'good', 'time'],...] 

Depuis les phrases dans le fichier étaient en lignes distinctes, elle renvoie la liste des listes et defaultdict ne peut pas identifier la jetons individuels à compter.

a essayé la compréhension de la liste ci-dessous pour isoler les jetons dans les différentes listes et de les retourner à une liste unique, mais il retourne une liste vide à la place:

sent2 = [[w for w in word] for word in sent] 

est-il un moyen de faire cette liste à l'aide compréhensions? Ou peut-être un autre moyen plus facile?

+1

@Sven La solution de Marnach est bonne. Une solution générale au problème de vouloir dénier une liste imbriquée est l'utilisation de 'itertools.chain()'. Voir http://ideone.com/g4YMu –

Répondre

4

Il suffit d'utiliser une boucle imbriquée dans la compréhension de la liste:

sent = [word for line in f for word in line.lower().split()] 

Il existe des alternatives à cette approche, par exemple en utilisant itertools.chain.from_iterable(), mais je pense que la boucle imbriquée est beaucoup plus facile dans ce cas.

0

La compréhension des listes peut faire l'affaire mais accumulera tout en mémoire. Pour les gros intrants, cela pourrait être un coût inacceptable. La solution ci-dessous n'accumulera pas de grandes quantités de données en mémoire, même pour les gros fichiers. Le produit final est un dictionnaire de la forme {token: occurrences}.

import itertools 

def distinct_tokens(filename): 
    tokendict = {} 
    f = open(filename, 'r') 
    tokens = itertools.imap(lambda L: iter(L.lower.split()), f) 
    for tok in itertools.chain.from_iterable(tokens): 
    if tok in tokendict: 
     tokendict[tok] += 1 
    else: 
     tokendict[tok] = 1 
    f.close() 
    return tokendict 
+0

'iflatten()' existe déjà dans la bibliothèque standard. Il s'appelle 'itertools.chain.from_iterable()'. –

+0

Mis à jour le code dans ma réponse. – wberry

1

Il suffit de lire l'intégralité du fichier à la mémoire, un s une seule chaîne, et appliquer une fois split chaîne de chapeau tot. Il n'est pas nécessaire de lire le fichier ligne par ligne dans un tel cas.

Par conséquent, votre coeur peut être aussi courte que:

sent = open("music.txt").read().split() 

(quelques subtilités comme la fermeture du fichier, la vérification des erreurs, tourner le code un peu plus grand, bien sûr)

Puisque vous voulez Pour compter les fréquences des mots, vous pouvez utiliser les collections. Classe de compteur pour cela:

from collections import Counter 
counter = Counter() 
for word in open("music.txt").read().split(): 
    counter[word] += 1 
+0

Vous n'initialisez pas 'counter'. Et vous n'avez pas besoin de la boucle - 'Counter (open (" music.txt "). Read(). Split())' suffira. –

+0

@SvenMarnach: ah..merci, je ne me rappelais pas comment initialiser le compteur de cette façon. D'un autre côté, le faire comme je l'ai fait suppose que les clés non existantes contiennent '0' - donc ce code fonctionne. – jsbueno

+0

Ce que je voulais dire - votre code manque de la ligne 'counter = Counter()'. Je sais que c'est une remarque insignifiante, et j'ai * up * voté votre réponse. :) (La deuxième partie de mon commentaire précédent n'avait aucun rapport avec la première partie.) –

Questions connexes