从两个列表中删除共同元素。

5

我有两个正整数排序列表,它们可以有重复元素,我必须从每个列表中删除匹配的数字对:

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

should become:

a=[1,2,2]
b=[4,5,5]

也就是说,2和3已经被删除了,因为它们在两个列表中都出现了。

由于有重复元素,无法使用集合交集。

我该怎么做?


1
我已经尝试过,但是看不出输入和输出之间的联系。可能需要更多的示例/进一步的解释来帮助理解... - Jon Clements
1
我认为这是因为应该从两个列表中都删除3以及其中一个2。 - nrussell
我理解在进行序列比对时,应该从两个序列中删除重叠的片段。正确吗? - tzelleke
5个回答

4
为了删除同时出现在两个列表中的元素,请使用以下方法:
for i in a[:]:
    if i in b:
        a.remove(i)
        b.remove(i)

创建一个自动执行此操作的函数,只需执行以下步骤:
```html

要创建此函数,请执行以下操作:

```
def removeCommonElements(a, b):
    for e in a[:]:
        if e in b:
            a.remove(e)
            b.remove(e)

或者返回新的列表而不是编辑旧的列表:
def getWithoutCommonElements(a, b): # Name subject to change
    a2 = a.copy()
    b2 = b.copy()
    for e in a:
        if e not in b:
            a2.remove(e)
            b2.remove(e)
    return a2, b2

然而,前者可以被替换为removeCommonElements,方法如下:
a2, b2 = a.copy(), b.copy()
removeCommonElements(a2, b2)

保留a和b,但是创建一个没有共同元素的重复。

这对于列表 a=[1,2,2,2,3]b=[2,2,3,4,5] 不起作用,它会使 a=[1,2,3]b=[3,4,5] - nrussell
1
不要在删除列表元素时遍历列表。将 iter(a) 替换为 a[:] 即可解决问题。 - pemistahl
不完全符合我的需求:[1,1,3],[1,1,1] 返回 [1, 3],[1, 1],应该返回 [3],[1],因为有两个匹配的1。 - Antoni Gual Via
@AntoniGualVia 是的,我已经修复了它,请尝试使用新版本。 - user1632861
@AntoniGualVia 如果答案对你有用,请记得接受它 :) - user1632861

2

从collections中的Counter对象可以非常简洁地实现此操作:

from collections import Counter
a=Counter([1,2,2,2,3])
b=Counter([2,3,4,5,5])
print list((a-b).elements())
print list((b-a).elements())

思路如下:
  1. 统计每个元素出现的次数(例如,2在a中出现了3次,在b中出现了1次)
  2. 减去计数以确定该元素额外出现的次数(例如,2在a中比b多出现了3-1=2次)
  3. 输出每个元素额外出现的次数(collections中的elements方法会自动删除计数小于1的元素)
(注意:输出列表不一定按顺序排列)

2
鉴于列表已排序,您可以逐个合并/分配元素,例如:
x, y = [], []

while a and b:
    if a[0] < b[0]:
        x.append(a.pop(0))
    elif a[0] > b[0]:
        y.append(b.pop(0))
    else: # a[0]==b[0]
        a.pop(0)
        b.pop(0)

x += a
y += b

1
@Mahi 给出的解决方案几乎是正确的。实现您想要的最简单的方法是这样的:
def remove_common_elements(a, b):
    for i in a[:]:
        if i in b:
            a.remove(i)
            b.remove(i)
     return a, b

重要的是通过写入 a [:] 来复制 a。如果您在从列表中删除元素时迭代该列表,则不会获得正确的结果。
如果您不想直接修改列表,请事先复制两个列表并返回复制的列表。
def remove_common_elements(a, b):
    a_new = a[:]
    b_new = b[:]
    for i in a:
        if i in b_new:
            a_new.remove(i)
            b_new.remove(i)
    return a_new, b_new

0
一个解决方案是创建a的新副本并从b中删除共同元素。
a = [1,2,2,2,3]
b = [2,2,3,4,5]

a_new = []
for ai in a:
    if ai in b:
        b.remove(ai)
    else:
        a_new.append(ai)

print a_new
print b

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接