Velocity Reviews > iterating over a list as if it were a circular list

# iterating over a list as if it were a circular list

Sven
Guest
Posts: n/a

 03-07-2013
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[i] 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
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.

--
../Sven

Alexander Blinne
Guest
Posts: n/a

 03-07-2013
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[i] 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/ite...ertools.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/ran...random.shuffle

untested:

import random

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

Greetings

Alexander Blinne
Guest
Posts: n/a

 03-07-2013
Am 08.03.2013 00:49, schrieb Alexander Blinne:
> http://docs.python.org/3/library/ite...ertools.repeat

obviously I was aiming for
http://docs.python.org/2/library/ite...tertools.cycle
here....

Greetings

Steven D'Aprano
Guest
Posts: n/a

 03-08-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