简体   繁体   中英

Removing common elements in two lists

I have two sorted lists of positive integers which can have repeated elements and I must remove matching pairs of numbers, one from each list:

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

should become:

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

That is, the 2's and the 3's have been removed because they appear in both lists.

Set intersection can't be used here because of the repeated elements.

How do I go about this?

To remove elements appearing in both lists, use the following:

for i in a[:]:
    if i in b:
        a.remove(i)
        b.remove(i)

To create a function which does it for you, simply do:

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

Or to return new lists and not to edit the old ones:

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

However the former could be replaced with removeCommonElements like so:

a2, b2 = a.copy(), b.copy()
removeCommonElements(a2, b2)

Which would keep a and b, but create a duplicates without common elements.

The Counter object from collections can do this quite concisely:

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())

The idea is:

  1. Count up how often each element appears (eg 2 appears 3 times in a, and 1 time in b)
  2. Subtract the counts to work out how many extra times the element appears (eg 2 appears 3-1=2 times more in a than b)
  3. Output each element the extra number of times it appears (the collections elements method automatically drops any elements with counts less than 1)

(Warning: the output lists won't necessarily be sorted)

Given that the lists are sorted, you can merge/distribute element-wise, like for example:

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

The solution given by @Mahi is nearly correct. The simplest way to achieve what you want is this:

def remove_common_elements(a, b):
    for i in a[:]:
        if i in b:
            a.remove(i)
            b.remove(i)
     return a, b

The important thing here is to make a copy of a by writing a[:] . If you iterate through a list while removing elements from it, you won't get correct results.

If you don't want to modify the lists in place, make a copy of both lists beforehand and return the copied lists.

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

One solution would be to create a new copy of a and removing common elements from 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM