使用Python 3查找两个具有重复元素的列表之间的公共项

v64noz0r  于 2023-05-30  发布在  Python
关注(0)|答案(3)|浏览(167)

很多postsHow to find list intersection?的目标是在两个列表之间找到unique个项目:
以下是我的两个清单:

list1=[1, 2, 2, 3, 3, 4, 4, 5, 10, 12] 
list2=[1, 1, 2, 2, 3, 4, 4, 5, 8, 18]

我的答案是找到共同的项目,可以重复的项目。例如,一个1出现在这两个列表中,因此,res应该包含一个1。两个2出现在两个列表中,res应该包含两个2,以此类推。

res = [1 ,2, 2, 3, 4, 4, 5]

顺序无关紧要,我的尝试是用途:

res = [x for x in list2 if x in list1]
# res = [1, 1, 2, 2, 3, 4, 4, 5] by above code

但是,这是不正确的,那么我该怎么做呢?

tzcvj98z

tzcvj98z1#

我能想到的唯一方法是从list2中删除项目:

list1 = [1, 2, 2, 3, 3, 4, 4, 5, 10, 12]
list2 = [1, 1, 2, 2, 3, 4, 4, 5, 8, 18]

res = []

for x in list1:
    if x in list2:
        res.append(x)
        list2.remove(x)

print(res)

我很好奇是否有更好的答案。

ctzwtxfj

ctzwtxfj2#

传统的方法不起作用,因为在第二个for循环中,它再次迭代整个列表,并再次找到相同的元素,即使它在前面被考虑过。
你需要一种机制来消除已经考虑过的元素。
例如:当你在list2上迭代list1,遇到3。在第一次迭代中,您将在list2中找到它。但是,当您继续前进并考虑下一个元素3时,您将再次发现它是list2中的公共元素,因为您从一开始就迭代list2

解决方案:

一旦我们在list2中遇到重复的元素,我们就从list2中删除它。

a = [1, 2, 2, 3, 3, 4, 4, 5, 10, 12]
b = [1, 1, 2, 2, 3, 4, 4, 5, 8, 18]

def remove_duplicates(x,y):
    res = []
    for i in x:
        for j in y:
            if j == i:
                res.append(j)
                y.remove(j)
    return res
    
print(remove_duplicates(a,b))

另一种使用函数式编程的方法是将list2转换为使用map()的数据结构,以便它为列表中的每个元素保存两个值:[(1, True),(2, True), ...]
迭代时,仅访问设置为True的元素
而且,每当我们找到一个公共元素时,我们将该元素的True设置为False

ruarlubt

ruarlubt3#

基于计数器的替代解决方案:

import collections

def intersection(A,B):
    c_a=collections.Counter(A)
    c_b=collections.Counter(B)
    duplicates=[]
    for c in c_a:
        duplicates+=[c]*min(c_a[c],c_b[c])
    return duplicates

list1=[1, 2, 2, 3, 3, 4, 4, 5, 10, 12] 
list2=[1, 1, 2, 2, 3, 4, 4, 5, 8, 18]
print(intersection(list1,list2))

相关问题