This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: sets needs an 'arbitrary element' method
Type: enhancement Stage:
Components: Library (Lib) Versions:
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: Nosy List: georg.brandl, mkc, mwh, rhettinger
Priority: normal Keywords:

Created on 2005-05-31 15:54 by mkc, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Messages (6)
msg54547 - (view) Author: Mike Coleman (mkc) Date: 2005-05-31 15:54
It would be nice to have an "arbitrary element" method
that would return some arbitrary element of a non-empty
set (throwing an exception if the set is empty). 
Something like this

>>> s = sets.Set([1,2,3])
>>> print s.element()
2

AFAIK, the current alternative would be to do something
like this

>>> print list(s)[0]

which is somewhat expensive and unreadable.

It'd be fine if the operator returned the same or a
different element each time.  Perhaps it'd be useful if
it returned the same element each time for frozen sets.
msg54548 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2005-05-31 15:59
Logged In: YES 
user_id=1188172

For mutable sets, I think that pop() is better suited. Do
you have a use case of your proposal with frozensets?
msg54549 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2005-05-31 16:54
Logged In: YES 
user_id=80475

I had looked at putting in a choose() method but there were
a shortage of use cases that were not better served by pop()
or by iteration.  Will leave this open as the request may
yet prove its worth.  To do so, I would need to see examples
of practical code where choose() is a better choice than
existing alternatives.

For the record, here were some of the lines of thinking
about choose(). 

* Given that any element could be returned, it was logical
to return the first encountered.  That led to the odd
situation where the method would return the same value on
every call (unless followed by a set mutation) making the
method useless in a loop. 

* If needed, an efficient alternative is available: 
iter(s).next(). And here is a more readable, encapsulated
version that a programmer could dash off in seconds:

   def choose(s, default=None):
       for elem in s:
           return elem
       return default

* I had looked at a few textbook algorithms that were
expressed in terms of choose().  Without exception, their
Python code was better expressed using pop(),  In a couple
of cases, the pop() needed to be followed by an add() if the
item was to be left in the set.  Those two cases all had
other set mutations occuring on each iteration (otherwise,
the pop/add pair would always get the same element).
msg54550 - (view) Author: Mike Coleman (mkc) Date: 2005-06-03 20:45
Logged In: YES 
user_id=555

I like rhettinger's "iter(s).next()" solution quite well,
except that it's kind of an obscure way to say "give me an
element of this set".  I'm completely okay with the idea
that the choose method may or may not return the same
element each time--I just want a "for example" element.

To my thinking, pop() isn't really a good solution because
it treats sets and frozensets differently.  Plus a
pop()/add() cycle seems wasteful and confusing.  One could
argue that in the other place where pop() is available
(lists), there is also a simple way to "peek" at what would
be popped, which is kind of what we're talking about here.

As for a use case, I'm not sure I have a great one.  This
came up when I was writing some union/find code.  I was
using sets to represent equivalence classes and I wanted to
be able to grab a representative of a set (which would be
any element of the set), given the set.  I was surprised to
find that there didn't seem to be a straightforward way to
do this.

I agree that I could just copy your 'choose' function into
my code easily.  There are several such functions that I
already copy into pretty much every script I write these
days (warn, error, and groupby, which probably do just what
you think they do).  If it's something that would be broadly
useful, though, it seems like it'd be a lot more efficient
for everyone to know the function by the same name (i.e., by
having it be in the standard library).



msg54551 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2005-06-14 08:41
Logged In: YES 
user_id=80475

Closed due to lack of use cases and my deep suspicion that
it is the wrong thing to do.
msg54552 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2005-06-14 10:14
Logged In: YES 
user_id=6656

Just a comment that I've actually wanted this function
recently; in the case where the set has a single element, it
can be interesting to know what that element is.

It's not a big thing, iter(s).next() works, but it's obscure.
History
Date User Action Args
2022-04-11 14:56:11adminsetgithub: 42033
2005-05-31 15:54:41mkccreate