当两个可迭代对象之一为无限时如何获得笛卡尔积 [英] How to get Cartesian product of two iterables when one of them is infinite

查看:72
本文介绍了当两个可迭代对象之一为无限时如何获得笛卡尔积的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

比方说,我有两个迭代,一个有限和一个无限:

Let's say I have two iterables, one finite and one infinite:

import itertools

teams = ['A', 'B', 'C']
steps = itertools.count(0, 100)

我想知道是否可以避免嵌套的for循环并使用

I was wondering if I can avoid the nested for loop and use one of the infinite iterators from the itertools module like cycle or repeat to get the Cartesian product of these iterables.

循环应该是无限的,因为steps的停止值是预先未知的.

The loop should be infinite because the stop value for steps is unknown upfront.

预期输出:

$ python3 test.py  
A 0
B 0
C 0
A 100
B 100
C 100
A 200
B 200
C 200
etc...

具有嵌套循环的工作代码:

Working code with nested loops:

from itertools import count, cycle, repeat

STEP = 100 
LIMIT = 500
TEAMS = ['A', 'B', 'C']


def test01():
    for step in count(0, STEP):
        for team in TEAMS:
            print(team, step)
        if step >= LIMIT:  # Limit for testing
            break

test01()

推荐答案

尝试如文档所述,product(A, B)等同于((x,y) for x in A for y in B). 如您所见,product生成一个元组,这意味着它是一个生成器,并且不会在内存中创建列表以正常工作.

As the docs say product(A, B) is equivalent to ((x,y) for x in A for y in B). As you can see, product yield a tuple, which mean it's a generator and do not create a list in memory in order to work properly.

此函数大致等效于以下代码,不同之处在于实际实现不会在内存中建立中间结果:

This function is roughly equivalent to the following code, except that the actual implementation does not build up intermediate results in memory:

def product(*args, **kwds):
    # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
    # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
    pools = map(tuple, args) * kwds.get('repeat', 1)
    result = [[]]
    for pool in pools:
        result = [x+[y] for x in result for y in pool]
    for prod in result:
        yield tuple(prod)

但是由于已知问题,您不能将itertools.product用于无限循环:

But you can't use itertools.product for infinite loop due to a known issue:

根据文档,itertools.product等效于 在生成器表达式中嵌套的for循环.但, itertools.product(itertools.count(2010))不是.

According to the documentation, itertools.product is equivalent to nested for-loops in a generator expression. But, itertools.product(itertools.count(2010)) is not.

>>> import itertools
>>> (year for year in itertools.count(2010))
<generator object <genexpr> at 0x026367D8>
>>> itertools.product(itertools.count(2010))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
MemoryError

itertools.product的输入必须是有限的有限序列 迭代器.

The input to itertools.product must be a finite sequence of finite iterables.

对于无限循环,您可以使用此代码.

For infinite loop, you can use this code.

这篇关于当两个可迭代对象之一为无限时如何获得笛卡尔积的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆