1

Im working with the next code:

for u in G:
    if u.count('L')>1:
        while (u in G)==True:
            G.remove(u)
print G

Where G is a list of strings with the letters O,A and L. The problem is that, inclusive when u.count('L') is greater than 1, the object u doesn't goes from the list. How can i repair this? Thanks.

[Edit] For a example of the list I'm using, here it is: https://www.dropbox.com/s/qiv2jq4xlg0d5sg/list.txt

iam_agf
  • 639
  • 2
  • 9
  • 20
  • 1
    Are you trying to remove all "L"s in `G`? This won't do that. What's the expected outcome and what is the output you're getting? – Adam Smith Dec 31 '13 at 20:57
  • I'm triying to quit the elements that have double 'L'. – iam_agf Dec 31 '13 at 20:58
  • 1
    First: Never try to modify a list while looping over it. Second: never use `remove` to delete a specific value from a list when you know where it is; use `del G[idx]`. To get the index along with the value, use `for idx, i in enumerate(G):`. – abarnert Dec 31 '13 at 20:59
  • Can we see an example of the list, along with what data you're trying to remove? Is it something like `["A","O","L","A","L","L","O"]` and you're trying to remove only the `"L","L"`? or only one of those "L"s? I'm confused. – Adam Smith Dec 31 '13 at 21:00
  • But if the element is repeated? – iam_agf Dec 31 '13 at 21:00
  • Yes, but is very big: https://www.dropbox.com/s/qiv2jq4xlg0d5sg/list.txt – iam_agf Dec 31 '13 at 21:02
  • @abarnet, what is the issue with using remove? – wnnmaw Dec 31 '13 at 21:03
  • @MonsieurGalois and you're trying to ignore any of those elements that have "LL" in them anywhere? – Adam Smith Dec 31 '13 at 21:03
  • 2
    @wnnmaw because `list.remove(value)` removes the first occurrence of `value` in a list, not necessarily the one you want. If you're looping through a list you should be able to use `enumerate(list)` to get the index and `del list[index]` to be more explicit – Adam Smith Dec 31 '13 at 21:08
  • 2
    @wnnmaw also, because `list.remove(v)` has to seek the value, even if it gets the one you want it's a more expensive operation. – kojiro Dec 31 '13 at 21:12

3 Answers3

4

You seem to be trying to remove words that contain more than one consecutive 'L' in them.

input: ['ALL', 'APPLE', 'LLAMA', 'LAX', 'PALLOR']

output: ['APPLE', 'LAX']

Here are some approaches:

List Comprehension

lyst[:] = [word for word in lyst if 'LL' not in word]

(the [:] part says to put the new list in the same place the old one was. It's not very important for small lists, but makes it look like you know what you're doing.)

Filter

lyst = filter(lambda word: 'LL' not in word, lyst)

(You could do the [:] trick again with filter in Python 2, but in Python 3 filter doesn't return a list, so I left it out.)

For loop

How not to do it:

for i, word in enumerate(lyst):
  if 'LL' in word:
    del lyst[i]

Why not? It seems to work with the above list, but look at the indices that are being nuked:

>>> lyst = ['ALL', 'APPLE', 'LLAMA', 'LAX', 'PALLOR']
>>> for i,w in enumerate(lyst):
...   print i,w
...   if 'LL' in w:
...     del lyst[i]
... 
0 ALL
1 LLAMA
2 PALLOR

That's no good! "LLAMA"'s index didn't start out as 1. We can break this algorithm by changing the input list:

>>> lyst=['APPLE', 'ALL', 'LLAMA', 'LAX', 'PALLOR']
>>> for i,w in enumerate(lyst):
...   print i,w
...   if 'LL' in w: 
...     del lyst[i]
... 
0 APPLE
1 ALL
2 LAX
3 PALLOR
>>> lyst
['APPLE', 'LLAMA', 'LAX']

The list comprehension or filter approaches are probably the best, but if you really prefer to write out your loops, you must go in reverse to avoid the indices changing out from under you:

>>> for i, w in reversed(list(enumerate(lyst))):
...   print i,w
...   if 'LL' in w:
...     del lyst[i]
... 
4 PALLOR
3 LAX
2 LLAMA
1 ALL
0 APPLE
>>> lyst
['APPLE', 'LAX']
Community
  • 1
  • 1
kojiro
  • 74,557
  • 19
  • 143
  • 201
  • This looks to me to be the most faithful answer to OP's question. I believe that what he's doing is exactly that -- building a list with every element except those that contain "LL" – Adam Smith Dec 31 '13 at 21:05
1

You cannot remove elements from a list while iterating over it using a for loop in Python. Instead, try a list comprehension:

>>> G = ['ALL', 'ALM', 'AMM', 'ANM', 'LAL' ]

>>> # if you want to remove words with more than one 'L'
>>> H = [ u for u in G if u.count('L') <= 1 ]
>>> H
['ALM', 'AMM', 'ANM']

>>> # if you want to remove words with consecutive Ls, i.e. 'LL'
>>> H = [ u for u in G if 'LL' not in u ]
>>> H
['ALM', 'AMM', 'ANM', 'LAL']

Updated: I added a demo of how to remove words that contain consecutive Ls, which seems to be the most likely task the OP is trying to accomplish.

mdml
  • 22,442
  • 8
  • 58
  • 66
0

If you want to remove all strings containing L from a list just do

G = [s for s in G if 'L' not in s]
Iguananaut
  • 21,810
  • 5
  • 50
  • 63