我想在一个单词列表中找到最常见的字母.我正在努力学习这个算法,因为我只需要在跳过重复项时只计算一个单词中的字母频率,所以我需要帮助找到一种方法来计算整个列表中字母的频率,每个单词只出现一次,忽略了第二次出现.
例如,如果我有:
words = ["tree", "bone", "indigo", "developer"]
频率将是:
letters={a:0, b:1, c:0, d:2, e:3, f:0, g:1, h:0, i:1, j:0, k:0, l:1, m:0, n:2, o:3, p:1, q:0, r:2, s:0, t:1, u:0, v:1, w:0, x:0, y:0, z:0}
从字母词典中可以看出:'e'是3而不是5,因为如果'e'在同一个单词中重复多次,则应忽略它.
这是我提出的算法,它是用Python实现的:
for word in words:
count=0;
for letter in word:
if(letter.isalpha()):
if((letters[letter.lower()] > 0 && count == 0) ||
(letters[letter.lower()] == 0 && count == 0)):
letters[letter.lower()]+=1
count=1
elif(letters[letter.lower()]==0 && count==1):
letters[letter.lower()]+=1
但它仍然需要工作,我无法想到任何其他事情,我会很高兴有人帮我思考一个有效的解决方案.
1> Daniel Mesej..:
@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})
基本上将每个单词转换为一个集合,然后迭代每个集合.
2> Primusa..:
创建一个计数器对象,然后使用每个单词的集合更新它:
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.
将该解决方案的时间复杂度与OP提供的时间复杂度进行比较将是有帮助的
@JordanSinger我认为它们是同一时间的复杂性,两种解决方案都会迭代每个单词中的每个字符; 我只是使用`set`来筛选重复项
3> mad_..:
一个没有柜台
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}
4> Ralf..:
比较目前提供的解决方案的速度:
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()
).