在Python中不使用集合找出两个列表的公共元素

11 投票
3 回答
17671 浏览
提问于 2025-04-15 22:06

我想要统计两个列表中相同元素的数量。这两个列表可能会有重复的元素,所以我不能把它们转换成集合来用&和运算符。

a=[2,2,1,1]
b=[1,1,3,3]

用set(a) & set(b)可以得到结果
但是用a & b就不行

有没有办法不使用集合和字典来实现这个呢?

3 个回答

0

SilentGhost、Mark Dickinson 和 Lo'oris 说得对,非常感谢你们报告这个问题 - 我需要找出两个列表的共同部分,所以对于:

a=[1,1,1,2]

b=[1,1,3,3]

结果应该是 [1,1]

抱歉在不合适的地方评论 - 我今天刚注册。

我修改了你们的解决方案:

def count_common(l1,l2):
        l2_copy=list(l2)
        counter=0
        for i in l1:
            if i in l2_copy:
                counter+=1
                l2_copy.remove(i)
        return counter

l1=[1,1,1]
l2=[1,2]
print count_common(l1,l2)

1

8

使用集合是最有效的方法,但你也可以这样做:r = [i for i in l1 if i in l2]

12

在Python 3.x(还有Python 2.7发布时),你可以使用collections.Counter来实现这个功能:

>>> from collections import Counter
>>> list((Counter([2,2,1,1]) & Counter([1,3,3,1])).elements())
[1, 1]

这里还有一个替代方案,使用collections.defaultdict(在Python 2.5及以后的版本中可用)。这个方法有个好处,就是结果的顺序是确定的(基本上和第二个列表的顺序一致)。

from collections import defaultdict

def list_intersection(list1, list2):
    bag = defaultdict(int)
    for elt in list1:
        bag[elt] += 1

    result = []
    for elt in list2:
        if elt in bag:
            # remove elt from bag, making sure
            # that bag counts are kept positive
            if bag[elt] == 1:
                del bag[elt]
            else:
                bag[elt] -= 1
            result.append(elt)

    return result

对于这两种解决方案,输出列表中任何给定元素x的出现次数是两个输入列表中x出现次数的最小值。你的问题中并没有明确说明你是否想要这样的行为。

撰写回答