Частота подсчета букв в списке слов, исключая дубликаты в одном слове

Его предполагаемое использование должно быть не только для этих сторонних модулей. Он не упоминается должным образом в документации Python (или, может быть, я просто не мог этого найти), но эллипсис ... фактически используется в CPython по крайней мере в одном месте.

Он используется для представления бесконечных структур данных в Python. Я столкнулся с этой нотой, играя со списками.

Для получения дополнительной информации см. этот вопрос .

41
задан lexual 15 February 2019 в 01:31
поделиться

9 ответов

from collections import Counter  
import string  

words=["tree","bone","indigo","developer"]  
y=Counter(string.ascii_lowercase)  
new_dict=dict(y) 

for k in new_dict:  
    new_dict[k]=0  
trial = 0  
while len(words) > trial:  
    for let in set(words[trial]):    
        if let in new_dict:  
            new_dict[str(let)]=new_dict[str(let)]+1  

    trial = trial +1  
print(new_dict)
0
ответ дан Edward Kaharo 15 February 2019 в 01:31
поделиться

Слишком поздно для вечеринки, но здесь вы идете:

freq = {k: sum(k in word for word in words) for k in set(''.join(words))}

который возвращает:

{'i': 1, 'v': 1, 'p': 1, 'b': 1, 'e': 3, 'g': 1, 't': 1, 'n': 2, 'd': 2, 'o': 3, 'l': 1, 'r': 2}
0
ответ дан Ev. Kounis 15 February 2019 в 01:31
поделиться

Другие решения хороши, но они конкретно не включают буквы с нулевой частотой. Вот подход, который делает, но примерно в 2-3 раза медленнее, чем другие.

import string
counts = {c: len([w for w in words if c in w.lower()]) for c in string.ascii_lowercase}

, который выдает подобное: ] https://github.com/dwyl/english-words/

import string
import timeit
import random
from collections import Counter

def f1(words):
    c = Counter()
    for word in words:
        c.update(set(word.lower()))
    return c

def f2(words):
    return Counter(
        c
        for word in words
        for c in set(word.lower()))

def f3(words):
    d = {}
    for word in words:
        for i in set(word.lower()):
            d[i] = d.get(i, 0) + 1
    return d


def f4(words):
    d = {c: len([w for w in words if c in w.lower()]) for c in string.ascii_lowercase} 
    return d


with open('words.txt') as word_file:
    valid_words = set(word_file.read().split())

for exp in range(5):

    result_list = []
    for i in range(1, 5):
        t = timeit.timeit(
            'f(words)',
            'from __main__ import f{} as f, valid_words, exp; import random; words = random.sample(valid_words, 10**exp)'.format(i),
            number=100)
        result_list.append((i, t))

    print('{:10,d} words | {}'.format(
        len(words),
        ' | '.join(
            'f{} {:8.4f} sec'.format(i, t) for i, t in result_list)))

print(f4(random.sample(valid_words, 10000)))
print(f4(random.sample(valid_words, 1000)))
print(f4(random.sample(valid_words, 100)))
print(f4(random.sample(valid_words, 10)))

0
ответ дан Stobor 15 February 2019 в 01:31
поделиться
import collections
import itertools
import string


def main():
    words = ["tree", "bone", "indigo", "developer"]
    no_repeated_letters = (set(word) for word in words)
    letter_stream = itertools.chain.from_iterable(no_repeated_letters)
    counter = collections.Counter(letter_stream)
    # set zeros for unseen letters, to match poster's answer.
    for letter in string.ascii_lowercase:
        if letter not in counter:
            counter[letter] = 0
    # print result.
    for key in sorted(counter):
        print(key, counter[key])


if __name__ == '__main__':
    main()
0
ответ дан lexual 15 February 2019 в 01:31
поделиться

Сравнение скорости решений, представленных до сих пор:

def f1(words):
    c = Counter()
    for word in words:
        c.update(set(word.lower()))
    return c

def f2(words):
    return Counter(
        c
        for word in words
        for c in set(word.lower()))

def f3(words):
    d = {}
    for word in words:
        for i in set(word.lower()):
            d[i] = d.get(i, 0) + 1
    return d

Моя функция синхронизации (используя разные размеры для списка слов):

word_list = [
    'tree', 'bone', 'indigo', 'developer', 'python',
    'language', 'timeit', 'xerox', 'printer', 'offset',
]

for exp in range(5):
    words = word_list * 10**exp

    result_list = []
    for i in range(1, 4):
        t = timeit.timeit(
            'f(words)',
            'from __main__ import words,  f{} as f'.format(i),
            number=100)
        result_list.append((i, t))

    print('{:10,d} words | {}'.format(
        len(words),
        ' | '.join(
            'f{} {:8.4f} sec'.format(i, t) for i, t in result_list)))

Результаты:

        10 words | f1   0.0028 sec | f2   0.0012 sec | f3   0.0011 sec
       100 words | f1   0.0245 sec | f2   0.0082 sec | f3   0.0113 sec
     1,000 words | f1   0.2450 sec | f2   0.0812 sec | f3   0.1134 sec
    10,000 words | f1   2.4601 sec | f2   0.8113 sec | f3   1.1335 sec
   100,000 words | f1  24.4195 sec | f2   8.1828 sec | f3  11.2167 sec

Counter со списком (здесь как f2()), кажется, самый быстрый. Использование counter.update() кажется медленной точкой (здесь как f1()).

0
ответ дан Ralf 15 February 2019 в 01:31
поделиться

Попробуйте использовать словарное понимание:

import string
print({k:max(i.count(k) for i in words) for k in string.ascii_lowercase})
0
ответ дан U9-Forward 15 February 2019 в 01:31
поделиться

Один без счетчика

words=["tree","bone","indigo","developer"]
d={}
for word in words:         # iterate over words
    for i in set(word):    # to remove the duplication of characters within word
        d[i]=d.get(i,0)+1

Выход

{'b': 1,
 'd': 2,
 'e': 3,
 'g': 1,
 'i': 1,
 'l': 1,
 'n': 2,
 'o': 3,
 'p': 1,
 'r': 2,
 't': 1,
 'v': 1}
0
ответ дан mad_ 15 February 2019 в 01:31
поделиться

Вариант ответа @Primusa без использования обновления:

from collections import Counter

words = ["tree", "bone", "indigo", "developer"]
counts = Counter(c for word in words for c in set(word.lower()) if c.isalpha())

Вывод

Counter({'e': 3, 'o': 3, 'r': 2, 'd': 2, 'n': 2, 'p': 1, 'i': 1, 'b': 1, 'v': 1, 'g': 1, 'l': 1, 't': 1})

В основном преобразует каждое слово в набор, а затем выполняет итерацию по каждому множество.

0
ответ дан Daniel Mesejo 15 February 2019 в 01:31
поделиться

Создайте объект счетчика, а затем обновите его наборами для каждого слова:

from collections import Counter

wordlist = ["tree","bone","indigo","developer"]

c = Counter()
for word in wordlist:
    c.update(set(word.lower()))

print(c)

Вывод:

Counter({'e': 3, 'o': 3, 'r': 2, 'n': 2, 'd': 2, 't': 1, 'b': 1, 'i': 1, 'g': 1, 'v': 1, 'p': 1, 'l': 1})

Обратите внимание, что хотя букв, которых не было в wordlist отсутствуют в Counter, это нормально, потому что Counter ведет себя как defaultdict(int), поэтому при доступе к отсутствующему значению автоматически возвращается значение по умолчанию, равное 0.

0
ответ дан Primusa 15 February 2019 в 01:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: