Suppose the following:
>>> s = set([1, 2, 3])
How do I get a value (any value) out of s
without doing s.pop()
? I want to leave the item in the set until I am sure I can remove it - something I can only be sure of after an asynchronous call to another host.
Quick and dirty:
>>> elem = s.pop()
>>> s.add(elem)
But do you know of a better way? Ideally in constant time.
To provide some timing figures behind the different approaches, consider the following code. The get() is my custom addition to Python's setobject.c, being just a pop() without removing the element.
The output is:
This means that the for/break solution is the fastest (sometimes faster than the custom get() solution).
Least code would be:
Obviously this would create a new list which contains each member of the set, so not great if your set is very large.
Since you want a random element, this will also work:
The documentation doesn't seem to mention performance of
random.sample
. From a really quick empirical test with a huge list and a huge set, it seems to be constant time for a list but not for the set. Also, iteration over a set isn't random; the order is undefined but predictable:If randomness is important and you need a bunch of elements in constant time (large sets), I'd use
random.sample
and convert to a list first:Following @wr. post, I get similar results (for Python3.5)
Output:
However, when changing the underlying set (e.g. call to
remove()
) things go badly for the iterable examples (for
,iter
):Results in:
tl;dr
for first_item in muh_set: break
remains the optimal approach in Python 3.x. Curse you, Guido.y u do this
Welcome to yet another set of Python 3.x timings, extrapolated from wr.'s excellent Python 2.x-specific response. Unlike AChampion's equally helpful Python 3.x-specific response, the timings below also time outlier solutions suggested above – including:
list(s)[0]
, John's novel sequence-based solution.random.sample(s, 1)
, dF.'s eclectic RNG-based solution.Code Snippets for Great Joy
Turn on, tune in, time it:
Quickly Obsoleted Timeless Timings
Behold! Ordered by fastest to slowest snippets:
Faceplants for the Whole Family
Unsurprisingly, manual iteration remains at least twice as fast as the next fastest solution. Although the gap has decreased from the Bad Old Python 2.x days (in which manual iteration was at least four times as fast), it disappoints the PEP 20 zealot in me that the most verbose solution is the best. At least converting a set into a list just to extract the first element of the set is as horrible as expected. Thank Guido, may his light continue to guide us.
Surprisingly, the RNG-based solution is absolutely horrible. List conversion is bad, but
random
really takes the awful-sauce cake. So much for the Random Number God.I just wish the amorphous They would PEP up a
set.get_first()
method for us already. If you're reading this, They: "Please. Do something."Two options that don't require copying the whole set:
Or...
But in general, sets don't support indexing or slicing.