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
  • 601
  • 1
  • 7
  • 17

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,364
  • 18
  • 40
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,378
  • 1
  • 8
  • 18
2
word = ['aaaaa', '@someword', '@otherword','bbbb']    
filtered = list(filter( lambda x : '@' not in x ,word))

another way is you can user filter

paras chauhan
  • 637
  • 4
  • 12
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
  • 218
  • 1
  • 5
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
  • 397
  • 3
  • 11