Pergunta

Suponha que eu tenho uma lista de palavras, e eu quero encontrar o número de vezes que cada palavra aparece nessa lista.

Uma forma óbvia de fazer isso é:

words = "apple banana apple strawberry banana lemon"
uniques = set(words.split())
freqs = [(item, words.split().count(item)) for item in uniques]
print(freqs)

Mas acho que este código não é muito bom, porque o programa é executado através da lista de palavras duas vezes: uma para construir o conjunto, e uma segunda vez para contar o número de aparências.

Claro, eu poderia escrever uma função para executar a lista e fazer a contagem, mas que não seria tão Pythonic. Então, há uma maneira mais eficiente e Pythonic?

Foi útil?

Solução

defaultdict para o resgate!

from collections import defaultdict

words = "apple banana apple strawberry banana lemon"

d = defaultdict(int)
for word in words.split():
    d[word] += 1

isto corre em O (n).

Outras dicas

O Counter classe no módulo collections é construído propositadamente para resolver este tipo de problema:

from collections import Counter
words = "apple banana apple strawberry banana lemon"
Counter(words.split())
# Counter({'apple': 2, 'banana': 2, 'strawberry': 1, 'lemon': 1})

abordagem padrão:

from collections import defaultdict

words = "apple banana apple strawberry banana lemon"
words = words.split()
result = collections.defaultdict(int)
for word in words:
    result[word] += 1

print result

groupby oneliner:

from itertools import groupby

words = "apple banana apple strawberry banana lemon"
words = words.split()

result = dict((key, len(list(group))) for key, group in groupby(sorted(words)))
print result
freqs = {}
for word in words:
    freqs[word] = freqs.get(word, 0) + 1 # fetch and increment OR initialize

Eu penso que este resultado para a mesma solução do Tríptico, mas sem importar coleções. Também um pouco como a solução da Selinap, mas IMHO mais legível. Quase idêntica à solução de Thomas Weigel, mas sem o uso de exceções.

Esta poderia ser mais lento do que usar defaultdict () a partir da biblioteca de coleções no entanto. Como o valor é buscado, incrementado e, em seguida, atribuído novamente. Em vez de apenas incrementado. No entanto usando + = pode fazer exatamente o mesmo internamente.

Se você não quiser usar o método de dicionário padrão (loop através da lista incrementando o dict adequada chave.), Você pode tentar o seguinte:

>>> from itertools import groupby
>>> myList = words.split() # ['apple', 'banana', 'apple', 'strawberry', 'banana', 'lemon']
>>> [(k, len(list(g))) for k, g in groupby(sorted(myList))]
[('apple', 2), ('banana', 2), ('lemon', 1), ('strawberry', 1)]

Corre-se em O (N log N) tempo.

Sem defaultdict:

words = "apple banana apple strawberry banana lemon"
my_count = {}
for word in words.split():
    try: my_count[word] += 1
    except KeyError: my_count[word] = 1

Você não pode simplesmente usar contagem?

words = 'the quick brown fox jumps over the lazy gray dog'
words.count('z')
#output: 1

Aconteceu de eu trabalhar em algum exercício Spark, aqui está a minha solução.

tokens = ['quick', 'brown', 'fox', 'jumps', 'lazy', 'dog']

print {n: float(tokens.count(n))/float(len(tokens)) for n in tokens}

** # saída do acima **

{'brown': 0.16666666666666666, 'lazy': 0.16666666666666666, 'jumps': 0.16666666666666666, 'fox': 0.16666666666666666, 'dog': 0.16666666666666666, 'quick': 0.16666666666666666}

Use reduzir () para converter a lista para um único dict.

words = "apple banana apple strawberry banana lemon"
reduce( lambda d, c: d.update([(c, d.get(c,0)+1)]) or d, words.split(), {})

volta

{'strawberry': 1, 'lemon': 1, 'apple': 2, 'banana': 2}
words = "apple banana apple strawberry banana lemon"
w=words.split()
e=list(set(w))       
for i in e:
   print(w.count(i))    #Prints frequency of every word in the list

Espero que isso ajude!

A resposta abaixo leva alguns ciclos extra, mas é outro método

def func(tup):
    return tup[-1]


def print_words(filename):
    f = open("small.txt",'r')
    whole_content = (f.read()).lower()
    print whole_content
    list_content = whole_content.split()
    dict = {}
    for one_word in list_content:
        dict[one_word] = 0
    for one_word in list_content:
        dict[one_word] += 1
    print dict.items()
    print sorted(dict.items(),key=func)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top