iterating over a list as if it were a circular list

S

Sven

Stupid keyboard shortcuts, sent it too early. Apologies


I was wondering what the best approach for the following might be.

Say you have a list P of points and another list N of other items. You can
always assume that

len(N) <= len(P)

Now I would like to iterate over P and place one N at each point. However
if you run out of N I'd like to restart from N[0] and carry on until all
the points have been populated.
So far I've got (pseudo code)

i = 0
for point in points:
put N at point
if i > len(N):
i = 0

is this the most pythonic way to accomplish this?

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.
 
A

Alexander Blinne

Am 07.03.2013 10:27, schrieb Sven:
Now I would like to iterate over P and place one N at each point.
However if you run out of N I'd like to restart from N[0] and carry on
until all the points have been populated.
So far I've got (pseudo code)

i = 0
for point in points:
put N at point
if i > len(N):
i = 0

is this the most pythonic way to accomplish this?


Sounds like
http://docs.python.org/3/library/itertools.html#itertools.repeat
to me.
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.

This can be done with
http://docs.python.org/3/library/random.html#random.shuffle

untested:

import random

def repeated_random_permutation(iterable):
pool = list(iterable)
while True:
random.shuffle(pool)
yield from pool


Greetings
 
S

Steven D'Aprano

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)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,981
Messages
2,570,188
Members
46,732
Latest member
ArronPalin

Latest Threads

Top