# Re: two generators working in tandem

Discussion in 'Python' started by Michael Spencer, Feb 10, 2006.

1. ### Michael SpencerGuest

john peter wrote:
> I'd like to write two generators: one is a min to max sequence number generator that
> rolls over to min again once the max is reached. the other is a generator that cycles
> through N (say, 12) labels. currently, i'm using these generators in nested loops like
> this:
>
> seq_numbers = genSeqNum(min,max)
> for label in genLabel():
> for some_date in genDate(init):
> for i in xrange(0, LIMIT):
> print label, some_date, i, seq_numbers.next()
>
> The problem I'm trying to solve is this:
> when the seq_numbers generator rolls over, the label generator must be advanced
> to the next one "in tandem". does anyone has any suggestion? thanks for any hepl!
>
>
> ---------------------------------
> Yahoo! Mail
> Use Photomail to share photos without annoying attachments.
>

This returns an iterator that 'nests' an arbitrary number of sequences
(odometer-style).

def nest(*sequences):
def _nest(outer, inner):
for outer_item in outer:
if not isinstance(outer_item, tuple):
outer_item = (outer_item,)
for inner_item in inner:
yield outer_item + (inner_item,)
return reduce(_nest, sequences)

>>> seq_numbers = range(1,10)
>>> labels = ["A","B","C"]
>>> list(nest(labels, seq_numbers))

[('A', 1), ('A', 2), ('A', 3), ('A', 4), ('A', 5), ('A', 6), ('A', 7), ('A',
8), ('A', 9), ('B', 1), ('B', 2), ('B', 3), ('B', 4), ('B', 5), ('B', 6), ('B',
7), ('B', 8), ('B', 9), ('C', 1), ('C', 2), ('C', 3), ('C', 4), ('C', 5), ('C',
6), ('C', 7), ('C', 8), ('C', 9)]
>>>

HTH, Michael

Michael Spencer, Feb 10, 2006

2. ### Anton VredegoorGuest

Michael Spencer wrote:

> This returns an iterator that 'nests' an arbitrary number of sequences
> (odometer-style).
>
> def nest(*sequences):
> def _nest(outer, inner):
> for outer_item in outer:
> if not isinstance(outer_item, tuple):
> outer_item = (outer_item,)
> for inner_item in inner:
> yield outer_item + (inner_item,)
> return reduce(_nest, sequences)

Nice!

Here's a nonrecursive version. It creates a list of iterators that are
repeating their values just enough times to sychronize the nesting. I
wonder if 'ncycle' would be a useful generalization for itertools'
'cycle' function.

Anton

def ncycle(seq,n):
while True:
for x in seq:
for dummy in xrange(n):
yield x

def cross(*args):
p = 1
R = []
for arg in args[::-1]:
L = list(arg)
R.append(ncycle(L,p))
p *= len(L)
R.reverse()
for dummy in xrange(p):
yield [x.next() for x in R]

def test():
s1='a1','a2','a3','a4'
s2='b1','b2'
s3='c1','c2','c3'
for x in cross(s1,s2,s3):
print x

if __name__=='__main__':
test()

Anton Vredegoor, Feb 12, 2006