Before 3.6 I would simply use set.pop()
. Now, sets are ordered and pop always removes from the start.
What do you think is the most pythonic way?
I'm not sure how I feel about set.remove(random.sample(set, 1)[0])
.
Before 3.6 I would simply use set.pop()
. Now, sets are ordered and pop always removes from the start.
What do you think is the most pythonic way?
I'm not sure how I feel about set.remove(random.sample(set, 1)[0])
.
Python 3.10 and lower:
The set .pop()
method does not accept a parameter, it removes an arbitrary (but not random) set value. https://docs.python.org/3.6/library/stdtypes.html#set.pop
Take a set sample with one element random.sample(s, 1)
and use set.remove()
.
>>> s = set([1,2,3,4,5])
>>> el = random.sample(s, 1)[0]
>>> s.remove(el)
>>> print(s)
{1, 3, 4, 5}
The random.choice
does not work because sets are not indexed.
>>> random.choice(s)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.5/random.py", line 256, in choice
return seq[i]
TypeError: 'set' object is not subscriptable
For Python 3.9 and later, random sampling from a set has been deprecated, as mentioned by @dangel in a comment on another answer to this question, and as described in the last paragraph of the docs, a very relevant SO answer, and another SO question.
You must now sample from a list
or tuple
. (I tested a numpy.array
and got the same TypeError as with a set
. See numpy's choice function for an alternative approach if you're using arrays.) It seems the most straight-forward pythonic way to do this is probably
sampled_item = random.sample(list(my_set), 1)[0]
my_set.remove(sampled_item)
This is a little longer than OP's suggested one-liners, but it's also pretty readable and the intent is clear. The TypeError (TypeError: Population must be a sequence. For dicts or sets, use sorted(d).
) recommends using sorted
rather than list
, but I don't see the point of sorting before random sampling see comments on this.