简体   繁体   中英

How can I lazily generate and process combinations of results from a generator?

I have a generator, and I'd like to perform a nested loop on it in such a way that the inner loop will start from where the outer loop stands at the moment. For example, I have a generator that produces the list [1,2,3] , and my loop should produce: (1,2),(1,3),(2,3) . The code I came up with is the following:

from itertools import tee

def my_gen():
    my_list = [1, 2, 3]
    for x in my_list:
        yield  x

first_it = my_gen()
while True:
    try:
        a = next(first_it)
        first_it, second_it = tee(first_it)
        for b in second_it:
            print(a,b)
    except StopIteration:
        break

This code is cumbersome, not efficient and does not look very pythonic to me. Please notice that I cannot use combinations_with_replacement because I need an inner loop for processing a specific value from the outer loop.

Any suggestions for a more elegant and pythonic code?

The repeated cloning and exhausting of only one of the resulting iterators is not very efficient. As per the itertools.tee docs :

In general, if one iterator uses most or all of the data before another iterator starts, it is faster to use list() instead of tee().

from itertools import islice

my_list = [1, 2, 3]
# or, more generally
# my_list = list(my_gen())

for i, a in enumerate(my_list):
    for b in islice(my_list, i+1, None):
        print((a, b))
(1, 2)
(1, 3)
(2, 3)

The result (1,2),(1,3),(2,3) isn't the cartesian product. Do you mean to obtain all the combinations without repetition?

For combinations without repetition

Use itertools.combinations function:

from itertools import combinations

print(list(combinations([1,2,3], 2)))

For actual cartesian product

Using list comprehension you can reduce your code into a more pythonic and elegant way:

my_list = [1, 2, 3]

c_prod = [(i, j) for i in iter(my_list) for j in iter(my_list)]

print(c_prod)

Another choice is to use the itertools.product function:

import itertools

for i in itertools.product(my_list, my_list):
    print(i)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM