1

There is a problem with removing successive elements from a list. For example I have an list;

['aaaaa', '@someword', '@otherword','bbbb',...]

I want remove from list elements that has @ char.

a = ['aaaaa', '@someword', '@otherword','bbbb']
for word in a:
    if '@' in word:
        print("found @ in word :" +word)
        a.remove(word)

The output is; (found only first element, skipped second one.)

found @ in word :@someword

if I add some value between this element;

a = ['aaaaa', '@someword', 'qqqq', '@otherword','bbbb']

It catch two of them;

found @ in word :@someword
found @ in word :@otherword

I debug the code, if there are succesive somewords which include @ char, remove function skip the second one, because of the changing of indices after removing process.

how can i remove these words?

babeyh
  • 659
  • 2
  • 7
  • 19

6 Answers6

2

You can use a list comprehension to filter out elements based on a condition:

>>> original = ['aaaaa', '@someword', '@otherword','bbbb']
>>> filtered = [item for item in original if '@' not in item]
>>> filtered
['aaaaa', 'bbbb']

Or replace them:

>>> replaced = [item if '@' not in item else '' for item in original]
>>> replaced
['aaaaa', '', '', 'bbbb']

See documentation for more info. Hope it helps!

Felix
  • 2,548
  • 19
  • 48
2

You should never change a list you are iterating through, but rather make a new one:

b = [word for word in a if not '@' in word]
user8408080
  • 2,428
  • 1
  • 10
  • 19
2
word = ['aaaaa', '@someword', '@otherword','bbbb']    
filtered = list(filter( lambda x : '@' not in x ,word))

another way is you can user filter

paras chauhan
  • 777
  • 4
  • 13
1

you need to add the list 'a' into a list. The below code might help you

a = ['aaaaa', '@someword', '@otherword','bbbb']
for word in list(a):
    if '@' in word:
        print("found @ in word :" +word)
        a.remove(word)
Manoj biroj
  • 288
  • 1
  • 6
1

It's not advisable to mutate the element of a list while you're looping over it.

a = ['aaaaa', '@someword', '@otherword','bbbb'] 
for index,word in enumerate(a):
    print(index, word)
    if '@' in word:
        a.remove(word)
        print(a)

The output of this is

(0, 'aaaaa')
(1, '@someword')
['aaaaa', '@otherword', 'bbbb']
(2, 'bbbb')

From this you can see that '@someword' is deleted and the element at index 2 is no longer '@otherword' it is now 'bbbb'. Therefore '@otherword' can not be deleted.

The second example you gave works because when you delete '@someword' the element at index 2 becomes '@otherword' therefore it can be deleted on the next iteration.

(0, 'aaaaa')
(1, '@someword')
['aaaaa', 'qqqq', '@otherword', 'bbbb']
(2, '@otherword')
['aaaaa', 'qqqq', 'bbbb']

I'll advise you to create a new list and just store the elements that don't contain '@' in it

a = ['aaaaa', '@someword', 'qqqq', '@otherword','bbbb']
new_list = [i for i in a if '@' not in i]
print(new_list) # ['aaaaa', 'qqqq', 'bbbb']
Tega Erekata
  • 11
  • 1
  • 1
1

The actual problem here is that you are looping through a list that you are editing(removing/adding items). This means that when you remove item 2 while you're on the second item, you will then reach item 4 in the next iteration.

Solutions are to loop over a copy of the list, or to create a copy of the list and return that (with list comprehension for example)

A copy of the list can be created with word[:].

a = ['aaaaa', '@someword', '@otherword','bbbb']
for word in a[:]:
    if '@' in word:
        print("found @ in word :" +word)
        a.remove(word)
Steven Stip
  • 387
  • 3
  • 11