找到两个iterable共享的匹配值的数量的更有效的方法?

2024-03-29 09:40:57 发布

您现在位置:Python中文网/ 问答频道 /正文

编辑:查找匹配数而不是匹配本身。无法用集合或[x for x in list1 if x in list2]类型方式进行求解。list1.count(x) if x in list2虽然有效。

假设您有两个列表,list1和list2,并且希望找到list1中的值与list2中的值匹配的次数。你知道吗

我使用以下代码成功执行此任务-

sum([x==y for x in list1 for y in list2])

问题是这段代码不能有效地处理较大的列表。有没有一个更快,更有效,我敢说更python的方式来解决这个问题比“双为”循环?你知道吗


Tags: 代码in编辑类型列表forifcount
3条回答

我们可以使用Python标准库中的Counter。你知道吗

计数器计算在iterable中找到项的次数。从一个列表构造它本质上会产生一个从列表中的每个项目到出现次数的映射。你知道吗

在两个计数器上执行集合交集将为我们提供在两个列表中找到的项目的计数。但是,我们不是寻找重复的数量,而是寻找一个元素与另一个元素匹配的次数。这意味着我们需要使用乘法而不是最小的集合交集。你知道吗

from collections import Counter

def merge(d1, d2):
  return {k: (d1[k], d2[k]) for k in d1 if k in d2}

def num_dups(l1, l2):
  c1, c2 = Counter(l1), Counter(l2)
  dups = merge(c1, c2)
  return sum(x * y for x, y in dups.values())

这种方法与其他方法完全不同,而且对于您的需求来说可能过于简单化了——但是我想我还是把它放在一起。你知道吗

它解决了这一请求:

  • 假设您有两个列表,list1和list2,并且希望找到list1中的值与list2中的值匹配的次数。

怎么样:

a = ['a', 'b', 'c', 'd', 'e']
b = ['a', 'a', 'c', 'c', 'c']

[b.count(i) for i in a]

输出:

[2, 0, 3, 0, 0]

计数器使用&运算符支持多集交集:

>>> from collections import Counter
>>> list1 = list("abba")   
>>> list2 = list("bbanana") 
>>> c1 = Counter(list1)
>>> c2 = Counter(list2)
>>> sum(c1[k]*c2[k] for k in c1 & c2)  # O(n)
10
>>> sum([x==y for x in list1 for y in list2])  # O(n**2)
10

相关问题 更多 >