delete items from a set while iterating over it
Question:
I have a set myset
, and I have a function which iterates over it to perform some operation on its items and this operation ultimately deletes the item from the set.
Obviously, I cannot do it while still iterating over the original set. I can, however, do this:
mylist = list(myset)
for item in mylist:
# do sth
Is there any better way?
Answers:
This ought to work:
while myset:
item = myset.pop()
# do something
Or, if you need to remove items conditionally:
def test(item):
return item != "foo" # or whatever
myset = set(filter(test, myset))
First, using a set, as Zero Piraeus told us, you can
myset = set([3,4,5,6,2])
while myset:
myset.pop()
print(myset)
I added a print
method giving these outputs
>>>
set([3, 4, 5, 6])
set([4, 5, 6])
set([5, 6])
set([6])
set([])
If you want to stick to your choice for a list, I suggest you deep copy the list using a list comprehension, and loop over the copy, while removing items from original list. In my example, I make length of original list decrease at each loop.
l = list(myset)
l_copy = [x for x in l]
for k in l_copy:
l = l[1:]
print(l)
gives
>>>
[3, 4, 5, 6]
[4, 5, 6]
[5, 6]
[6]
[]
Let’s return all even numbers while modifying current set.
myset = set(range(1,5))
myset = filter(lambda x:x%2==0, myset)
print myset
Will return
>>> [2, 4]
If there is opportunity use always use lambda
it will make your life easier.
Another way could be :
s=set()
s.add(1)
s.add(2)
s.add(3)
s.add(4)
while len(s)>0:
v=next(iter(s))
s.remove(v)
Use the copy
library to make a copy of the set, iterate over the copy and remove from the original one. In case you want to stick to the for
loop and you want to iterate over one element only once – comes in handy if you don’t necessarily want to remove all the elements.
import copy
for item in copy.copy(myset):
myset.remove(item)
I have a set myset
, and I have a function which iterates over it to perform some operation on its items and this operation ultimately deletes the item from the set.
Obviously, I cannot do it while still iterating over the original set. I can, however, do this:
mylist = list(myset)
for item in mylist:
# do sth
Is there any better way?
This ought to work:
while myset:
item = myset.pop()
# do something
Or, if you need to remove items conditionally:
def test(item):
return item != "foo" # or whatever
myset = set(filter(test, myset))
First, using a set, as Zero Piraeus told us, you can
myset = set([3,4,5,6,2])
while myset:
myset.pop()
print(myset)
I added a print
method giving these outputs
>>>
set([3, 4, 5, 6])
set([4, 5, 6])
set([5, 6])
set([6])
set([])
If you want to stick to your choice for a list, I suggest you deep copy the list using a list comprehension, and loop over the copy, while removing items from original list. In my example, I make length of original list decrease at each loop.
l = list(myset)
l_copy = [x for x in l]
for k in l_copy:
l = l[1:]
print(l)
gives
>>>
[3, 4, 5, 6]
[4, 5, 6]
[5, 6]
[6]
[]
Let’s return all even numbers while modifying current set.
myset = set(range(1,5))
myset = filter(lambda x:x%2==0, myset)
print myset
Will return
>>> [2, 4]
If there is opportunity use always use lambda
it will make your life easier.
Another way could be :
s=set()
s.add(1)
s.add(2)
s.add(3)
s.add(4)
while len(s)>0:
v=next(iter(s))
s.remove(v)
Use the copy
library to make a copy of the set, iterate over the copy and remove from the original one. In case you want to stick to the for
loop and you want to iterate over one element only once – comes in handy if you don’t necessarily want to remove all the elements.
import copy
for item in copy.copy(myset):
myset.remove(item)