Python 根据两个列表中元组的出现情况更新defaultdict计数

Python 根据两个列表中元组的出现情况更新defaultdict计数,python,list,dictionary,tuples,counter,Python,List,Dictionary,Tuples,Counter,我有两个列表,想创建一个字典来记录元组的出现 我当前的代码: tup_to_find_test = [('good', 'pea'), ('leaf', 'sweet')] self_per_list_test = [('leaf', 'liquid'), ('leaf', 'sweet'), ('leaf', 'sweet'),('good', 'pea'),('good', 'pea'),('good', 'pea')] from collections import defaultdic

我有两个列表,想创建一个字典来记录元组的出现

我当前的代码:

tup_to_find_test = [('good', 'pea'), ('leaf', 'sweet')] 
self_per_list_test = [('leaf', 'liquid'), ('leaf', 'sweet'), ('leaf', 'sweet'),('good', 'pea'),('good', 'pea'),('good', 'pea')]
from collections import defaultdict
tup_dict_test = defaultdict(int)
for tup_to_find_test in self_per_list_test:
   tup_dict_test[tup_to_find_test]+=1
我的结果是:

defaultdict(int, {('leaf', 'liquid'): 1, ('leaf', 'sweet'): 1, ('good', 'pea'): 3})
('leaf', 'liquid'): 0, ('leaf', 'sweet'): 2, ('good', 'pea'): 3})
我期望的结果是:

defaultdict(int, {('leaf', 'liquid'): 1, ('leaf', 'sweet'): 1, ('good', 'pea'): 3})
('leaf', 'liquid'): 0, ('leaf', 'sweet'): 2, ('good', 'pea'): 3})
我不知道为什么
('leaf','liquid')
的计数是1。
defaultdict(int)
0的默认整数不是零吗?为什么我在
('leaf','liquid')
元组中得到了1

defaultdict(int)
0的默认整数不是零吗

为什么我的('leaf','liquid')元组得到1

你写道:

tup_dict_test[tup_to_find_test]+=1

也就是说,找到当前值,该值将创建一个设置为零的新值,然后向其中添加一个值,并将结果存储回去。结果值为1。

这一行没有执行您认为的操作:

for tup_to_find_test in self_per_list_test:
   # ...
在这里,您正在对列表元素进行迭代,在本例中,
self\u per\u list\u test
的元素。没有进行过滤。当您的
for
循环迭代时,
tup\u to\u find\u test
依次表示
('leaf','liquid')
('leaf','sweet')
,等等。该名称与前面定义的变量相同,这一事实只会让人感到困惑

相反,您可以使用三元语句来区分操作:

for item in self_per_list_test:
    tup_dict_test[item] += 1 if item in tup_to_find_test else 0

print(tup_dict_test)

defaultdict(int, {('leaf', 'liquid'): 0, ('leaf', 'sweet'): 2, ('good', 'pea'): 3})

Python更为惯用。在词典理解中使用
set
进行O(1)查找是一种很好的做法

from collections import Counter

tup_to_find_set = set(tup_to_find_test)
counts = Counter(self_per_list_test)

tup_dict_test = {k: v if k in tup_to_find_set else 0 for k, v in counts.items()}

print(tup_dict_test)

{('leaf', 'liquid'): 0, ('leaf', 'sweet'): 2, ('good', 'pea'): 3}

没有重新发明轮子。您可以使用奇妙的
集合
标准模块库中的
计数器

from collections import Counter

tup_to_find_test = [('good', 'pea'), ('leaf', 'sweet')] 
self_per_list_test = [('leaf', 'liquid'), ('leaf', 'sweet'), ('leaf', 'sweet'),('good', 'pea'),('good', 'pea'),('good', 'pea')]

c = Counter(self_per_list_test)

for key in c:
    if key not in tup_to_find_test:
        c[key] = 0

print(c)

>>Counter({('good', 'pea'): 3, ('leaf', 'sweet'): 2, ('leaf', 'liquid'): 0})

这里我们基于
self\u per\u list\u test
创建一个计数器,如果在
tup\u to\u find\u test
中找不到,则将计数更新为零。希望这是一种更直观的方法来解决您的问题。

您有一次
('leaf','liquid')
self\u per\u list\u test
。与
defaultdict
相比,
计数器
是否比使用
defaultdict
更快?嗯,您无法将
defaultdict
计数器
进行比较,
defaultdict
调用工厂函数以提供缺少的值。
计数器
经过优化,可计算散列值。在这个用例中,如果您的目的只是计数,我将使用
计数器
。我在我的数据集上尝试了这两种方法。你是对的。因为我的目标是简单地计算元组的频率,所以我应该选择
Counter
。感谢您的智能/直截了当的解决方案!(我想我对我的问题想得太多了)是的,希望能有帮助。如果您发现这里的任何答案都很有用,请接受帮助您解决问题的最佳答案。这是@BernardL solution的单线形式,对吗?它非常整洁和聪明!谢谢@艾比,是的,如果你想坚持使用
defaultdict
,它确实是一行。建议通过
set
使用哈希来提高效率。