gpt4 book ai didi

Python:使用字典理解/生成器计算列表中的出现次数

转载 作者:太空狗 更新时间:2023-10-29 22:22:18 24 4
gpt4 key购买 nike

我想写一些测试来分析 python 中不同操作的效率,即字典理解和字典生成器的比较。

为了对此进行测试,我想尝试一个简单的示例:使用字典计算列表中的单词数。

现在我知道您可以使用 collections.Counter(根据此处的答案:How can I count the occurrences of a list item in Python?)执行此操作,但我的目标是测试性能和内存。

一种“长手”的方法是在一个基本循环中进行。

from pprint import pprint

# Read in some text to create example data
with open('text.txt') as f:
words = f.read().split()

dict1 = {}
for w in words:
if not dict1.get(w):
dict1[w] = 1
else:
dict1[w] += 1
pprint(dict1)

结果:

{'a': 62,
'aback': 1,
'able': 1,
'abolished': 2,
'about': 6,
'accept': 1,
'accepted': 1,
'accord': 1,
'according': 1,
'across': 1,
...

然后我在尝试在字典理解中做同样的事情时遇到了一点困难:

dict2  = { w: 1 if not dict2.get(w) else dict2.get(w) + 1
for w in words }

我遇到了一个错误:

NameError: global name 'dict2' is not defined

我试着预先定义字典:

dict2 = {}
dict2 = { w: 1 if not dict2.get(w) else dict2.get(w) + 1
for w in words }
pprint(dict2)

但当然计数都设置为 1:

{'a': 1,
'aback': 1,
'able': 1,
'abolished': 1,
'about': 1,
'accept': 1,
'accepted': 1,
'accord': 1,
'according': 1,
'across': 1,
...

我在听写理解方面遇到了类似的问题:

dict3 = dict( (w, 1 if not dict2.get(w) else dict2.get(w) + 1)
for w in words)

所以我的问题是:如何最有效地使用字典理解/生成器来计算列表中出现的次数?

更新:@Rawing 建议了一种替代方法 {word:words.count(word) for word in set(words)} 但这会绕过我的机制尝试测试。

最佳答案

你不能使用 dict-comprehension 有效地做到这一点(至少在内存方面),因为那样你就必须在另一个字典中跟踪当前计数,即更多的内存消耗。以下是使用 dict-comprehension(完全不推荐 :-))的方法:

>>> words = list('asdsadDASDFASCSAASAS')
>>> dct = {}
>>> {w: 1 if w not in dct and not dct.update({w: 1})
else dct[w] + 1
if not dct.update({w: dct[w] + 1}) else 1 for w in words}
>>> dct
{'a': 2, 'A': 5, 's': 2, 'd': 2, 'F': 1, 'C': 1, 'S': 5, 'D': 2}

另一种方法是先对单词列表进行排序,然后使用 itertools.groupby 将它们分组,然后计算每组的长度。如果需要,可以在这里将 dict-comprehension 转换为生成器,但是是的,这需要先读取内存中的所有单词:

from itertools import groupby
words.sort()
dct = {k: sum(1 for _ in g) for k, g in groupby(words)}

请注意,最快的collections.defaultdict:

d = defaultdict(int)
for w in words: d[w] += 1

时序比较:

>>> from string import ascii_letters, digits
>>> %timeit words = list(ascii_letters+digits)*10**4; words.sort(); {k: sum(1 for _ in g) for k, g in groupby(words)}
10 loops, best of 3: 131 ms per loop
>>> %timeit words = list(ascii_letters+digits)*10**4; Counter(words)
10 loops, best of 3: 169 ms per loop
>>> %timeit words = list(ascii_letters+digits)*10**4; dct = {}; {w: 1 if w not in dct and not dct.update({w: 1}) else dct[w] + 1 if not dct.update({w: dct[w] + 1}) else 1 for w in words}
1 loops, best of 3: 315 ms per loop
>>> %%timeit
... words = list(ascii_letters+digits)*10**4
... d = defaultdict(int)
... for w in words: d[w] += 1
...
10 loops, best of 3: 57.1 ms per loop
>>> %%timeit
words = list(ascii_letters+digits)*10**4
d = {}
for w in words: d[w] = d.get(w, 0) + 1
...
10 loops, best of 3: 108 ms per loop

#Increase input size

>>> %timeit words = list(ascii_letters+digits)*10**5; words.sort(); {k: sum(1 for _ in g) for k, g in groupby(words)}
1 loops, best of 3: 1.44 s per loop
>>> %timeit words = list(ascii_letters+digits)*10**5; Counter(words)
1 loops, best of 3: 1.7 s per loop
>>> %timeit words = list(ascii_letters+digits)*10**5; dct = {}; {w: 1 if w not in dct and not dct.update({w: 1}) else dct[w] + 1 if not dct.update({w: dct[w] + 1}) else 1 for w in words}

1 loops, best of 3: 3.19 s per loop
>>> %%timeit
words = list(ascii_letters+digits)*10**5
d = defaultdict(int)
for w in words: d[w] += 1
...
1 loops, best of 3: 571 ms per loop
>>> %%timeit
words = list(ascii_letters+digits)*10**5
d = {}
for w in words: d[w] = d.get(w, 0) + 1
...
1 loops, best of 3: 1.1 s per loop

关于Python:使用字典理解/生成器计算列表中的出现次数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26731675/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com