
On Fri, 10 Jul 2020 at 06:56, Chris Angelico <rosuav@gmail.com> wrote:
On Fri, Jul 10, 2020 at 3:41 PM Inada Naoki <songofacandy@gmail.com> wrote:
On Fri, Jul 10, 2020 at 1:53 PM Chris Angelico <rosuav@gmail.com> 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