当前位置: 首页 > 面试题库 >

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

支阳波
2023-03-14
问题内容

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

为了验证这一点,我想我会尝试一个简单的示例:使用字典计算列表中的单词数。

现在,我知道您可以使用collections.Counter(按照这里的答案:如何计算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,
 ...

我对dict理解有类似的问题:

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使用理解计算发生次数,包括了Python使用理解计算发生次数的使用技巧和注意事项,需要的朋友参考一下 示例 当我们要计算满足一定条件的可迭代项的数量时,可以使用理解来生成惯用语法: 基本概念可以概括为: 遍历中的元素range(1000)。 连接所有所需if条件。 使用1作为表达式,为每个符合条件的项目返回1。 对所有1s求和,以确定满足条件的项目数。 注意:这里我们没有

  • 问题内容: 我有一个Python列表,我想知道在此列表中计算项目出现次数的最快方法。在我的实际情况下,该项目可能会发生数万次,这就是为什么我想要一种快速的方法。 哪种方法:或更优化? 问题答案: a = [‘1’, ‘1’, ‘1’, ‘1’, ‘1’, ‘1’, ‘2’, ‘2’, ‘2’, ‘2’, ‘7’, ‘7’, ‘7’, ‘10’, ‘10’] print a.count(“1”) 它

  • 本文向大家介绍计算Python列表中元素的出现,包括了计算Python列表中元素的出现的使用技巧和注意事项,需要的朋友参考一下 在本文中,我们给出了一个列表和一个字符串。我们需要查找给定字符串作为元素存在于列表中的次数。 带柜台 来自collections模块的counter函数将为我们提供列表中每个元素的计数。从计数结果中,我们只能提取公平的那个指数,该指数与我们要搜索的元素的值匹配。 示例 输

  • 本文向大家介绍python列表生成式与列表生成器的使用,包括了python列表生成式与列表生成器的使用的使用技巧和注意事项,需要的朋友参考一下 列表生成式:会将所有的结果全部计算出来,把结果存放到内存中,如果列表中数据比较多,就会占用过多的内存空间,可能会导致MemoryError内存错误或者导致程序在运行时出现卡顿的情况 列表生成器:会创建一个列表生成器对象,不会一次性的把所有结果都计算出来,如

  • 问题内容: 什么时候应该使用生成器表达式,什么时候应该在中使用列表推导? 问题答案: John的答案很好(当你要迭代多次时,列表理解会更好)。但是,还应注意,如果要使用任何列表方法,都应使用列表。例如,以下代码将不起作用: 基本上,如果你要做的只是迭代一次,则使用生成器表达式。如果你要存储和使用生成的结果,那么列表理解可能会更好。 由于性能是选择彼此的最常见原因,所以我的建议是不要担心它,而只选择

  • 问题内容: 蟒蛇 我有一个清单清单。喜欢 我想计算每个列表在主列表中出现了多少次。 我的输出应该像 问题答案: 只需使用来自: