2017-10-18 25 views
2

Disons que j'ai un texte comme celui-ci:Nombre de fois par bigramme a été vu dans une liste jusqu'à un certain point

'he is hdajs asdas da he is not asd as da s i am a da daas you am a' 

J'ai créé toutes les bigrammes de ce texte:

>>> bigrams_ 
[('he', 'is'), ('is', 'hdajs'), ('hdajs', 'asdas'), ('asdas', 'da'), ('da', 'he'), ('he', 'is'), ('is', 'not'), ('not', 'asd'), ('asd', 'as'), ('as', 'da'), ('da', 's'), ('s', 'i'), ('i', 'am'), ('am', 'a'), ('a', 'da'), ('da', 'daas'), ('daas', 'you'), ('you', 'am'), ('am', 'a')] 

Maintenant, j'aime créer une nouvelle liste de bigrams où le premier élément de chaque bigram serait un index de position qui montre combien de fois un certain bigram du format ci-dessus a été vu jusqu'à un point dans le texte, et le second élément serait être le bigramme des mots de la liste initiale. Par exemple, dans la liste ci-dessus, le dernier élément ('am', 'a') a été vu 2 fois, donc dans la nouvelle liste il correspondrait à ce bigram: (2, ('am', 'a')). Ce serait une façon concise de faire cela.

+0

Comment est ' 'am' , 'a'' vu 3 fois? Cela ne se produit que deux fois dans votre texte, sauf s'il me manque quelque chose ici –

+0

Vous avez raison. Mes excuses. Je voulais dire 2 fois. –

+0

Sauf qu'il n'a été vu précédemment qu'une fois à droite, donc il devrait être '(1, ('am', 'a'))' - à moins que ce soit le nombre cumulé et que tout commence par '1'? –

Répondre

3

Vous pouvez utiliser un defaultdict avec une valeur par défaut d'un objet count et de prendre progressivement la valeur next du compteur de que les clés, par exemple:

from collections import defaultdict 
from itertools import count 

dd = defaultdict(lambda: count(1)) 
bigrams = [('he', 'is'), ('is', 'hdajs'), ('hdajs', 'asdas'), ('asdas', 'da'), ('da', 'he'), ('he', 'is'), ('is', 'not'), ('not', 'asd'), ('asd', 'as'), ('as', 'da'), ('da', 's'), ('s', 'i'), ('i', 'am'), ('am', 'a'), ('a', 'da'), ('da', 'daas'), ('daas', 'you'), ('you', 'am'), ('am', 'a')] 
with_count = [(next(dd[bigram]), bigram) for bigram in bigrams] 

Vous donne:

[(1, ('he', 'is')), 
(1, ('is', 'hdajs')), 
(1, ('hdajs', 'asdas')), 
(1, ('asdas', 'da')), 
(1, ('da', 'he')), 
(2, ('he', 'is')), 
(1, ('is', 'not')), 
(1, ('not', 'asd')), 
(1, ('asd', 'as')), 
(1, ('as', 'da')), 
(1, ('da', 's')), 
(1, ('s', 'i')), 
(1, ('i', 'am')), 
(1, ('am', 'a')), 
(1, ('a', 'da')), 
(1, ('da', 'daas')), 
(1, ('daas', 'you')), 
(1, ('you', 'am')), 
(2, ('am', 'a'))] 
+0

Je ne sais pas si c'est une bonne solution quand j'ai une liste de textes imbriqués. Par exemple, disons que j'ai ce texte «['je suis je suis vous êtes il', 'vous êtes il est je', 'je suis vous êtes']', où chaque phrase est un document séparé. Je veux réinitialiser les index lors du démarrage d'une nouvelle chaîne. Si j'écris '[[(next (indexer [elem]), elem) pour elem dans bigram] pour bigram dans bigrams]', il contiendra le comptage et l'incrémentation des indices de bigram, sans réinitialisation au début de chaque nouveau document. Le dernier ('i', 'am') dans la liste finale recevrait un index de 4, mais il est vu une fois dans le dernier document. –

+0

Eh bien ouais ... '.clear()' le compteur le cas échéant ou créer de nouveaux compteurs pour des sous-sections spécifiques ... –

+0

Merci. Donc, l'écrire avec la compréhension de la liste n'est probablement pas une bonne idée. –

0

Vous pouvez essayer ceci:

s = 'he is hdajs asdas da he is not asd as da s i am a da daas you am a' 
s1 = s.split() 
new_data = list(set([(s.count(' '.join(b)), b) for b in [(s1[i], s1[i+1]) for i in range(len(s1)-1)]])) 

Sortie:

[(2, ('am', 'a')), (1, ('da', 'daas')), (1, ('not', 'asd')), (1, ('s', 'i')), (1, ('da', 'he')), (1, ('you', 'am')), (2, ('he', 'is')), (1, ('is', 'not')), (1, ('asdas', 'da')), (1, ('asd', 'as')), (1, ('hdajs', 'asdas')), (1, ('a', 'da')), (1, ('daas', 'you')), (2, ('as', 'da')), (1, ('da', 's')), (1, ('is', 'hdajs')), (1, ('i', 'am'))] 
0

J'aime @JonClements itertools count solution à base de (+1), mais je ne pense pas defaultdict est nécessaire:

from itertools import count 

text = 'he is hdajs asdas da he is not asd as da s i am a da daas you am a' 

words = text.split() 

bigrams = zip(words, words[1:]) 

seen = dict() 

result = [(next(seen.setdefault(bigram, count(1))), bigram) for bigram in bigrams] 

print(*result, sep='\n') 

SORTIE

(1, ('he', 'is')) 
(1, ('is', 'hdajs')) 
(1, ('hdajs', 'asdas')) 
(1, ('asdas', 'da')) 
(1, ('da', 'he')) 
(2, ('he', 'is')) 
(1, ('is', 'not')) 
(1, ('not', 'asd')) 
(1, ('asd', 'as')) 
(1, ('as', 'da')) 
(1, ('da', 's')) 
(1, ('s', 'i')) 
(1, ('i', 'am')) 
(1, ('am', 'a')) 
(1, ('a', 'da')) 
(1, ('da', 'daas')) 
(1, ('daas', 'you')) 
(1, ('you', 'am')) 
(2, ('am', 'a'))