Lucas Sdott
Lucas Sdott

Reputation: 11

How are .pop and .index being used here?

I have a piece of code that I don't understand, I would appreciate it if someone could help me out.

list1 = [48, 33, 46, 46, 87, 11, 50, 99, 65, 87]    
list2 = [48, 33, 46]    
duplicates = [list1.pop(list1.index(i)) for i in list1 if i in list2]

Upvotes: 0

Views: 79

Answers (2)

atline
atline

Reputation: 31574

I believe your code does not meet your requirements:

You want to find which elements in list1 are also in list2. The result should be [48, 33, 46], but your result is [48, 46].

This is because after it finds 48 as a duplicate, 48 is deleted from list1. During this process, the index of 33 changes from 1 to 0. This means that the for can not iterate over this element, as now it wants to iterate from index 1. So 33 is missed.

The correct code is:

list1 = [48, 33, 46, 46, 87, 11, 50, 99, 65, 87]
list2 = [48, 33, 46]
# duplicates = [list1.pop(list1.index(i)) for i in list1 if i in list2]
duplicates = list(set([i for i in list1 if i in list2]))
print duplicates

And the main thing here is a python list comprehension.

Explain new code logic:

1. iterate 1st element of `list1` and find it in `list2`, so pick it.
2. repeat step 1
3. finally you get [48, 33, 46, 46], use `set` to change to [48, 33, 46], 
   and use `list` to chanage back to list

Your old code logic:

1. iterate 1st element of `list1` and find it in `list2`, so pick it.
2. after pick it, you get the index of 1st element, then pop it 
   (delete it from `list1` and return the element)
    so for this iterate, you get `48`
3. then you want to iterate 2rd element of `list1`, that supposed to be `33`;
   however, during the process of step2, you delete the `48`, so `33` becomes
   the 1st element, nolonger the 2rd element, so when you iterate, you missed
   the `33` & directly iterate to the `46`
4. for these not in `list2`, will not be handled.

Upvotes: 4

sacuL
sacuL

Reputation: 51335

Walk through it step by step, and it might make sense:

for i in list1 if i in list2 should make sense; it's the equivalent of

for i in list1:
    if i in list2:
        ...

list1.index(i) gets the index of i (each element in list1 that is found in list2), and finally list1.pop removes the item at that index from list1

Upvotes: 1

Related Questions