Reputation: 93
I don't have a specific piece of code that I want looked at; however, I do have a question that I can't seem to get a straight, clear answer.
Here's the question: if I have a set, I can iterate over it in a for loop. As I iterate over it can I remove specific numbers using .remove() or do I have to convert my set to a list first? If that is the case, why must I convert it first?
Upvotes: 3
Views: 1075
Reputation: 23099
This is how I'd do this:
myset = ...
newset = set()
while myset:
v = myset.pop()
if not do_i_want_to_delete_this_value(v):
newset.add(v)
myset = newset
A list comprehension will work too:
myset = set([x for x in myset if not do_i_want_to_delete_this_value(x)])
But this gets messy if you want to do other stuff while you're iterating and you don't want to wrap all that logic in a single function call. Nothing wrong with doing that though.
myset = set([x for x in myset if process_element(x)])
process_element() just has to return True/False to say if the element should be removed from the set.
Upvotes: 1
Reputation: 3025
@nathancy has already given a good explanation as to why deleting during iteration won't work, but I'd like to suggest an alternative: instead of doing the deletion at the same time as you iterate, do it instead as a second stage. So, you'd instead:
For instance:
def should_be_deleted(num):
return num % 2 == 0
my_set = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
to_delete = []
for value in my_set:
if should_be_deleted(value):
to_delete.append(value)
for value in to_delete:
my_set.remove(value)
print(my_set)
Prints:
set([1, 3, 5, 7, 9])
The same pattern can be applied to delete from any collection—not just set
, but also list
, dict
, etc.
Upvotes: 1
Reputation: 46620
In both cases, you should avoid iterating and removing items from a list or set. It's not a good idea to modify something that you're iterating through as you can get unexpected results. For instance, lets start with a set
numbers_set = {1,2,3,4,5,6}
for num in numbers_set:
numbers_set.remove(num)
print(numbers_set)
We attempt to iterate through and delete each number but we get this error.
Traceback (most recent call last):
File ".\test.py", line 2, in <module>
for num in numbers_set:
RuntimeError: Set changed size during iteration
Now you mentioned "do I have to convert my set to a list first?". Well lets test it out.
numbers_list = [1,2,3,4,5,6]
for num in numbers_list:
print(num)
numbers_list.remove(num)
print(numbers_list)
This is the result:
[2, 4, 6]
We would expect the list to be empty but it gave us this result. Whether you're trying to iterate through a list or a set and delete items, its generally not a good idea.
Upvotes: 1