On Fri, 10 Jul 2020 at 06:56, Chris Angelico <[email protected]> wrote:
>
> On Fri, Jul 10, 2020 at 3:41 PM Inada Naoki <[email protected]> wrote:
> >
> > On Fri, Jul 10, 2020 at 1:53 PM Chris Angelico <[email protected]> wrote:
> > >
> > >
> > > And immediately above that part, I said that I had made use of this,
> > > and had used it in Python by listifying the dict first. Okay, so I
> > > didn't actually dig up the code where I'd done this, but that's a use
> > > case. I have *actually done this*. In both languages.
> > >
> >
> > Do you pick random item repeatedly from same dictionary?
> > If so, you can create a list once in Python.
> >
>
> I would pick repeatedly from the same dictionary but it might be
> mutated in between. So the list would have to be reconstructed fresh
> every time.
Maybe there could be a function in the random module for making a
random choice from an arbitrary (finite) iterable:
# rnd.py
from random import randrange
def choice_iter(iterable):
iterator = iter(iterable)
try:
value = next(iterator)
except StopIteration:
raise ValueError("Empty iterable")
for n, candidate in enumerate(iterator, 2):
if not randrange(n):
value = candidate
return value
You could use that to get a choice from a dict, set etc. For a large
dict/set it will be slow compared to converting to a list because it's
calling randrange once per item. If you have a good reason not to
build the list though then you could use it. For example to get a
random line from a possibly large text file:
>>> from rnd import choice_iter
>>> with open('rnd.py') as fin:
... line = choice_iter(fin)
...
>>> line
' except StopIteration:\n'
It's not hard to generalise the function above to something that e.g.
makes a selection of k values from the iterable in a single pass. Here
is a version that works without replacement:
def sample_iter(population, k):
iterator = iter(population)
values = []
for _ in range(k):
try:
value = next(iterator)
except StopIteration:
raise ValueError("Too few items")
values.append(value)
for n, candidate in enumerate(iterator, k+1):
random_index = randrange(n)
if random_index < k:
values[random_index] = candidate
return values # maybe shuffle first?
--
Oscar
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/HKPSBX7FJ7MLQ4TUEBWMJ66YOQVVCT63/
Code of Conduct: http://python.org/psf/codeofconduct/