1

I have this code below. The first print statement prints out:

['c','a','t','d','o','g','r','a','b','b','i','t']

as expected

wlist = ['cat','dog','rabbit']
llist = [letter for word in wlist for letter in word]
tlist = []
print (llist)
for item in llist:
    if not item in tlist:
            tlist.append(item)
    else:
            llist.remove(item)
print (llist)

The second one, I expect it to print:

['c','a','t','d','o','g','r','b','i']

But it actually prints:

['c','d','o','g','r','a','b','b','i','t']

I do not understand why. I am trying to take every repeat occurrence of a letter out of llist. But the first occurrence seems to get taken out, and the two b's still remain. Can anyone explain to me how that happened?

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
DDauS
  • 105
  • 1
  • 2
  • 11
  • 1
    See [Remove items from a list while iterating in Python](http://stackoverflow.com/q/1207406) to properly delete items from a list while iterating. – Bhargav Rao Mar 13 '16 at 14:39
  • if you try to `print (llist)` at the end of each iteration, you will see that when you check for the letter `a` of the word rabbit, the `else` condition gets true, which will order for removal of `a` from `llist`. this removes the first appearance of that letter in the list which is the 2nd index, right after `c`. What you need is to do is get the index of the letter that you want to remove and then delete the character on the desired index. – Ahmed Dhanani Mar 13 '16 at 15:26

2 Answers2

1
else:
    llist.remove(item)

Here you are removing items from the list you are iterating. That generally causes a lot of problems since you make the loop skip elements then. You should always avoid mutating a list you are iterating.

If you remove that else case completely, you get the desired result. After all, there is no need to modify the source list.

poke
  • 369,085
  • 72
  • 557
  • 602
0

The problem is that you are modifying the list you are iterating over, which affects the pointer used by the iterator. Iterate over a copy instead:

for item in llist[:]:
    if item not in tlist:
        tlist.append(item)
    else:
        llist.remove(item)
chepner
  • 497,756
  • 71
  • 530
  • 681
  • Thanks, I understand my problem now. But what did you do with with [:] part? I'm guessing that makes a temporary list to iterate over and then removes the temp list at the end of the for loop? – DDauS Mar 13 '16 at 14:42
  • It creates a new object, via slicing, that happens to contain references to the same elements as the original. Now, you are iterating over the new anonymous list, but modifying the original. – chepner Mar 13 '16 at 14:43