[Python-ideas] random.choice on non-sequence
Grant Jenks
grant.jenks at gmail.com
Wed Apr 13 01:20:07 EDT 2016
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
More information about the Python-ideas
mailing list