Reputation: 699
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?
Upvotes: 1
Views: 253
Reputation: 2468
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]
Upvotes: 2
Reputation: 387
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)
Upvotes: 1
Reputation: 2668
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!
Upvotes: 2
Reputation: 11
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']
Upvotes: 1
Reputation: 787
word = ['aaaaa', '@someword', '@otherword','bbbb']
filtered = list(filter( lambda x : '@' not in x ,word))
another way is you can user filter
Upvotes: 2
Reputation: 323
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)
Upvotes: 1