iterating over a list as if it were a circular list
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Fri Mar 8 12:59:42 EST 2013
On Thu, 07 Mar 2013 09:27:42 +0000, Sven wrote:
> Additionally, what if I wanted to pull a random element from N, but I
> want to ensure all elements from N have been used before starting to
> pick already chosen random elements again. So far I thought of
> duplicating the list and removing the randomly chosen elements from the
> list, and when it's empty, re-copying it. But that seems a little
> "wrong" if you know what I mean.
An infinite generator is probably the best solution:
import random
def sample_without_replacement(alist):
blist = alist[:] # Copy the list.
while True:
random.shuffle(blist)
for value in blist:
yield value
Notice that I make a copy of the list before shuffling. That avoids side-
effects where calling sample_without_replacement on a list modifies it.
To use it, you do something like this:
it = sample_without_replacement([1, 2, 3, 4, 5, 6])
next(it)
=> prints a random value
next(it)
=> and a second random value
To grab twenty random values all at once, you can either do this:
it = sample_without_replacement([1, 2, 3, 4, 5, 6])
values = [next(it) for i in range(20)]
or this:
import itertools
it = sample_without_replacement([1, 2, 3, 4, 5, 6])
values = itertools.islice(it, 20)
--
Steven
More information about the Python-list
mailing list