[Python-Dev] Retrieve an arbitrary element from a set withoutremoving it

Steven D'Aprano steve at pearwood.info
Tue Nov 3 23:46:15 CET 2009


On Tue, 3 Nov 2009 09:19:38 am Greg Ewing wrote:
> Cameron Simpson wrote:
> > Personally, I'm for the iteration spec in a lot of ways.
> >
> > Firstly, a .get()/.pick() that always returns the same element
> > feels horrible. Is there anyone here who _likes_ it?
>
> It doesn't sound very useful to me. However, an iterating
> version of it doesn't sound any more useful. What would it
> gain you? Why not just iterate over the set? Or make a
> copy and repeatedly pop() it?

Since I was the person who decided that "arbitrary" meant "give a 
different result each time", I should answer that.

My intention was not that people should use repeated calls to pick() for 
iteration. I described that as an abuse of the method. But I can 
imagine scenarios where the caller calls set.pick() sequentially:

def pick_two_cards(hand):
    assert isinstance(hand, (set, frozenset))
    assert len(hand) == 5
    return (hand.pick(), hand.pick())


As I said in a reply to Raymond, optimization was not my primary 
concern, but as a fundamental set operation[1] pick() should be 
efficient. It may be called on a set with millions of items, not just 
small sets. Copying to another set, or to a list, will be O(N) and 
potentially slow -- at the very least, it is wasteful to copy millions 
of elements in order to access one.

I don't know how expensive it is to create a set iterator, but (my 
reasoning went) surely we can do better? The set already has access to 
its own elements, it just needs to return one of them. pop() also knows 
how to retrieve an arbitrary element. pick() is just like pop(), except 
without removal.


> I completely fail to see a use case for this.

Nevertheless, people keep requesting it, so obviously they have a use 
for it. None of the standard solutions are obvious or easily 
discoverable, and in my experience the usual solution people come up 
with is to pop() an element, then add() it back in, but of course 
that's not just inelegant but it fails on frozensets.



[1] Obviously there is disagreement on whether or not pick() is a 
fundamental operation or not. As Raymond points out, it is uncommon in 
other languages. But Wikipedia lists it as fundamental, and it is not 
just Python users who ask for it:

http://stackoverflow.com/questions/124671/picking-a-random-element-from-a-set


-- 
Steven D'Aprano


More information about the Python-Dev mailing list