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?

1
  • I agree: the reasons are the same, but it's difficult to see the link right away. Commented Oct 20, 2016 at 11:46

2 Answers 2

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) 
Sign up to request clarification or add additional context in comments.

3 Comments

You might want to include a link to this Question - the answer explains the problem in detail.
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.
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.
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']

1 Comment

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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.