6

Hi let's say that I have two lists in python and I want to remove common values from both lists. A potential solution is:

x = [1, 2, 3, 4, 5, 6, 7, 8]
y = [43, 3123, 543, 76, 879, 32, 14241, 342, 2, 3, 4]
for i in x:
    if i in y:
        x.remove(i)
        y.remove(i)

it seems correct but it is not. The reason, I guess, is because by removing an item from the list the index continues to iterate. Therefore, for two common values in the lists where the values are near each other we will be missing the later values (the code will not iterate through it). The result would be:

>>> x
[1, 3, 5, 6, 8, 9, 10]
>>> y
[43, 3123, 543, 76, 879, 32, 14241, 342, 3]

So we are missing the value '3'.

Is the reason of that behaviour the one that I mentioned? or am I doing something else wrong?

Rahul K P
  • 15,740
  • 4
  • 35
  • 52
MaPy
  • 505
  • 1
  • 6
  • 9
  • Yes, this is precisely the problem you will encounter by modifying a an object while iterating over it. – juanpa.arrivillaga May 17 '17 at 20:16
  • Please take a look at this question: [Remove items from a list while iterating](https://stackoverflow.com/questions/1207406/remove-items-from-a-list-while-iterating) – GIZ May 17 '17 at 20:18
  • 1
    It's strongly discouraged to modify the value you're iterating. This can make it difficult to determine the flow of the loop for anyone trying to comprehend what your code is doing. In this cases like this it is usually advisable to make modifications to a separate copy of your list (or other iterable object) or to iterate over an index to slice into your list: `for i in range(len(x)): print(x[i])` – Aaron May 17 '17 at 20:21

6 Answers6

10

Just slight change your code,Iterate through the copy of x it's x[:].You are modifying the list while iterating over it. So that's why you are missing value 3

for i in x[:]:
      if i in y:
          x.remove(i)
          y.remove(i)

And alternative method

x,y = [i for i in x if i not in y],[j for j in y if j not in x]
T K Sourabh
  • 351
  • 2
  • 8
Rahul K P
  • 15,740
  • 4
  • 35
  • 52
  • That doesn't work if there is a duplicated value in any list, try: `x = [1, 2, 3, 4, 5, 6, 7, 8, 3]` you have to also make a copy of y – DSLima90 May 17 '17 at 20:16
  • @DSLima90 I think that up to the OP requirement, If he want to remove the all occurance of duplicate it's won't work. But after the deletion from both list it's made unique in the first list. So that's not a problem. – Rahul K P May 17 '17 at 20:22
  • @Rhaul Yes, you are right. I assumed that OP wants to delete all occurrences by my interpretation of the code provided. It is a valid answer, though maybe it is worth noting that it differs from the other answers in that aspect so far. – DSLima90 May 17 '17 at 20:32
  • @DSLima90 May be you are right. Anyhow am updated with an alternative method – Rahul K P May 17 '17 at 20:39
8

You can also use difference of set objects.

a = list(set(y) - set(x))
b = list(set(x) - set(y))
vishes_shell
  • 22,409
  • 6
  • 71
  • 81
Taku
  • 31,927
  • 11
  • 74
  • 85
  • A downside of this is that it will remove all duplicate items and lose the ordering. But usually for people who wants to do this, it isn't a problem – Taku May 17 '17 at 20:20
3
z=[i for i in x if i not in y]
w=[i for i in y if i not in x]
x=z
y=w

That should do the trick? It's a bit less memory efficient.

Henry
  • 1,646
  • 12
  • 28
2

If you use numpy, then all you need is:

x, y = np.setdiff1d(x, y), np.setdiff1d(y, x)

and if you don't want to use numpy:

x, y = list(set(x).difference(y)), list(set(y).difference(x))
Gerges
  • 6,269
  • 2
  • 22
  • 44
2

I personally think Python's set data type is the way to go:

You can do something like this:

>>> x = [1, 2, 3, 4, 5, 6, 7, 8]
>>> y = [43, 3123, 543, 76, 879, 32, 14241, 342, 2, 3, 4]
>>> sx = set(x)
>>> sy = set(y)
>>> sx.union(sy)
set([1, 2, 3, 4, 5, 6, 7, 8, 32, 43, 76, 342, 543, 879, 3123, 14241])

Or you can reduce it to a one liner:

list(set(x).union(set(y)))
Mike Driscoll
  • 32,629
  • 8
  • 45
  • 88
-1

You can use set method to remove elements in list.

s1=input()
s2=input()
str=list(set(s1).symmetric_difference(set(s2)))
print(str)
davidbilla
  • 2,120
  • 1
  • 15
  • 26
Sanjai R
  • 31
  • 3