[Python-ideas] random.choice on non-sequence

Joao S. O. Bueno jsbueno at python.org.br
Wed Apr 13 01:29:28 EDT 2016


Maybe, instead of all of this, since as put by others, hardly there would be a
"one size fits all" - the nice thing to have would be a "choice" or
"randompop"  method for sets.

Sets are the one natural kind of object from which it would seen
normal to be able
to pick a random element (or pop one) - since they have no order to
start with, and
the one from which it is frustrating when one realizes "random.choice"
fails with,

So either have a "random.set_choice"  and "random.set_pop" functions
in random -
or "choice" and "pop_random" on the "set"  interface itself could be
more practical
- in terms of real world usage - than speculate a way for choice to
work in iterables
of unknown size, among other objects.

On 13 April 2016 at 02:20, Grant Jenks <grant.jenks at gmail.com> wrote:
> On Tue, Apr 12, 2016 at 2:40 PM, Rob Cliffe <rob.cliffe at btinternet.com> wrote:
>>
>> It surprised me a bit the first time I realised that random.choice did not
>> work on a set.  (One expects "everything" to "just work" in Python! :-) )
>
> As you point out in your proposed solution, the problem is `random.choice`
> expects an index-able value. You can easily create an index-able set using
> the sortedcontainers.SortedSet interface even if if the elements aren't
> comparable. Simply use:
>
> ```python
> from sortedcontainers import SortedSet
>
> def zero(value):
>     return 0
>
> class IndexableSet(SortedSet):
>     def __init__(self, *args, **kwargs):
>         super(IndexableSet, self).__init__(*args, key=zero, **kwargs)
>
> values = IndexableSet(range(100))
>
> import random
>
> random.choice(values)
> ```
>
> `__contains__`, `__iter__`, `len`, `add`, `__getitem__` and `__delitem__` will
> all be fast. But `discard` will take potentially linear time. So:
>
> ```
> index = random.randrange(len(values))
> value = values[index]
> del values[index]
> ```
>
> will be much faster than:
>
> ```
> value = random.choice(values)
> values.discard(value)
> ```
>
> Otherwise `IndexableSet` will work as a drop-in replacement for
> your `set` needs. Read more about the SortedContainers project at
> http://www.grantjenks.com/docs/sortedcontainers/
>
> Grant
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/


More information about the Python-ideas mailing list