How to get two synchronised generators from a function

Question:

i have a nested tuple like this one :

this_one = (w,h,(1,2,4,8,16),(0,2,3,4,6),("0"),("0"),(0,1))

It will be used to feed:
itertools.product(*this_one)

w and h have to be both generators.

Generated values from h depends on generated values from w as in this function:

def This_Function(maxvalue):

   for i in range(maxvalue):
       w_must_generate = i
       for j in range(i+1):
           h_must_generate = j         

Iv tried using a yield in This_function(maxvalue):

def This_Function(maxvalue):

   for i in range(maxvalue):
       for j in range(i+1):
           yield i,j

Returning a single generator object which gives:


which_gives = itertools.product(*this_one)
for result in which_gives:
    print(result)
...
((23,22),(16),(6),(0),(0),(0))
((23,22),(16),(6),(0),(0),(1))
((23,23),(1),(0),(0),(0),(0))
...

A single tuple at result[0] holding 2 values.

And this is not what i want .

The result i want has to be like the following:

the_following = itertools.product(*this_one)
for result in the_following:
    print(result)
...
((23),(22),(16),(6),(0),(0),(0))
((23),(22),(16),(6),(0),(0),(1))
((23),(23),(1),(0),(0),(0),(0))
...

Without having to do something like :

the_following = itertools.product(*this_one)
for result in the_following:
    something_like = tuple(result[0][0],result[0][1],result[1],...,result[5])
    print(something_like)
...
((23),(22),(16),(6),(0),(0),(0))
((23),(22),(16),(6),(0),(0),(1))
((23),(23),(1),(0),(0),(0),(0))
...

Any ideas ?

Asked By: On4r4p

||

Answers:

Since the values are all entirely determined, this works and is fairly legible:

from itertools import product

maxvalue = 5
w = (i for i in range(maxvalue) for j in range(i + 1))
h = (j for i in range(maxvalue) for j in range(i + 1))

this_one = (w, h, (1, 2, 4, 8, 16), (0, 2, 3, 4, 6), ("0"), ("0"), (0, 1))

result = product(*this_one)

The values yielded from w are basically 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, ... and the values yielded from h are 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, .... Plus, the code pretty much looks like your description of the desired behaviour, which is generally a good thing.

Both w and h are generators, no space is wasted and the solution is fairly optimal. I just can’t tell if result is what you actually need, but that depends on what you need and expect product() to do here.

Answered By: Grismar

That’s fundamentally not how product works. From the documentation:

Before product() runs, it completely consumes the input iterables, keeping pools of values in memory to generate the products. Accordingly, it is only useful with finite inputs.

Thus, having the second one be dependent won’t get you the result you want, assuming that is for h values to always be w+1..max in the resulting output sequence.

I’m not sure why you couldn’t just run it with your This_function approach and destructure it with a generator expression:

result = ((a, b, c, d, e, f, g) 
          for ((a, b), c, d, e, f, g) in itertools.product(*this_one))
Answered By: tzaman
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.