2

Hi i'm a newbie and i have a problem with a function. I have two lists:

>>> a = ['a0', 'b1', 'a2', 'b3', 'a4', 'b5']
>>> b = ['b0', 'a1', 'b2', 'a3', 'b4', 'b5']

I want to remove elements in common and the bigger one in the same position; my output should be:

>>> function(a,b)
>>> a
['a0', 'a2', 'a4']
>>> b
['a1', 'a3']

I tried this:

>>> def function(a,b):
        for i1,i2 in zip(a,b):
            if i1 == i2:
                a.remove(i1)
                b.remove(i2)
            elif i1 < i2:
                b.remove(i2)
            else:
                a.remove(i1) 

But it returns me:

>>> function(a,b)
>>> a
['a0', 'b1', 'a2', 'b3', 'a4', 'b5']
>>> b
['a1', 'a3', 'b5']

What's my mistake?

alex1997
  • 79
  • 6

2 Answers2

4

In python 2 that would work but in python 3 zip has become a generator function: it creates the items on demand (more info here about various zip, izip stuff and differences between 2 & 3)

Which means that since you're modifying a and b in the loop it amounts to iterating over changing lists (it's slightly less obivious because of the zip function).

To fix that, zip a copy of your input lists

def function(a,b):
        for i1,i2 in zip(a[:],b[:]):
            if i1 == i2:
                a.remove(i1)
                b.remove(i2)
            elif i1 < i2:
                b.remove(i2)
            else:
                a.remove(i1) 
Community
  • 1
  • 1
Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
  • 1
    You might want to include a link to [this](http://stackoverflow.com/questions/1663807/how-can-i-iterate-through-two-lists-in-parallel-in-python) Question - the answer explains the problem in detail. – Maurice Oct 20 '16 at 11:46
  • 1
    Note that this may not work if there are duplicate values in the list, since `remove` will take away the *first* occurrence. Might be better to remove by index. – brianpck Oct 20 '16 at 11:51
  • There would be a problem if there are duplicate values. that would mean to drop the `zip` stuff, and revert back to good old `while i < len(copy_of_a)` construct. – Jean-François Fabre Oct 20 '16 at 12:08
0

I have run your original code in my python 2.7 and it actually does output the values that you are looking for. But here is a more concise version for you to consider which also does the trick:

def function(a,b):
    for i1, i2 in zip(a,b):
        if i1 <= i2:
            b.remove(i2)
        if i2 <= i1:
            a.remove(i1)

a = ['a0', 'b1', 'a2', 'b3', 'a4', 'b5']
b = ['b0', 'a1', 'b2', 'a3', 'b4', 'b5']

function(a, b)


print a
>>>['a0', 'a2', 'a4']

print b
>>>['a1', 'a3']
RFV
  • 831
  • 8
  • 22
  • 1
    check the first sentence of my answer ... it works in python 2. That's not the point. and your "more concise" version performs 2 tests when equals whereas only 1 is needed. – Jean-François Fabre Oct 20 '16 at 13:54