如何使用生成器在Python中获得笛卡尔积?

2024-04-25 05:20:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图得到多个数组的笛卡尔积,但是数组非常大,我试图优化内存使用。我尝试使用下面的代码实现一个生成器,但它只是返回在某个位置有一个生成器

import itertools

x = [[1,2],[3,4]]

def iter_tools(*array):
    yield list(itertools.product(*array))

print(iter_tools(*x))

当我尝试相同的代码,但使用return而不是yield时,效果很好。如何通过实现生成器获得笛卡尔积


Tags: 内存代码importreturndef数组producttools
3条回答

生成器的思想是,您不会像调用list(itertools.product(*array))一样同时进行所有计算。因此,您要做的是一个接一个地生成结果。例如:

def iter_tools(*array):
    for i in array[0]:
        for j in array[1]:
            yield (i, j)

然后可以对每个结果元组执行如下操作:

for tup in iter_tools(*x):
    print(tup)

当然,您可以很容易地调整生成器,使其在每次调用中生成每行或每列

或者,如果您对itertools提供的服务感到满意:

for i in itertools.product(*x):
    print(i)

您需要什么取决于您的用例。希望我能帮助你:)

归根结底,itertools.product已经是一个iterator。你不需要自己写。(Agenerator是一种迭代器。)例如:

>>> x = [[1, 2], [3, 4]]
>>> p = itertools.product(*x)
>>> next(p)
(1, 3)
>>> next(p)
(1, 4)

现在,解释一下,你似乎误解了一些基本的东西。生成器函数返回一个generator iterator。这就是你从照片上看到的:

>>> iter_tools(*x)
<generator object iter_tools at 0x7f05d9bc3660>

使用list()将迭代器强制转换为列表

>>> list(iter_tools(*x))
[[(1, 3), (1, 4), (2, 3), (2, 4)]]

请注意它是如何嵌套的列表。这是因为你的iter_tools只会产生一个列表,而不会产生其他列表。在这一点上,这一部分毫无意义,因为将itertools.product强制转换到一个列表违背了迭代器lazy evaluation的全部目的。如果您确实希望从迭代器中生成值,则可以使用yield from

def iter_tools(*array):
    yield from itertools.product(*array)

在这种情况下iter_tools是没有意义的,但是如果实际的iter_tools更复杂,这可能就是您实际想要的

另见:


这个答案部分基于juanpa.arrivillagacomment

如果要从笛卡尔乘积中生成单个项,则需要迭代该乘积:

import itertools

x = [[1,2],[3,4]]

def iter_tools(*array):
    for a in itertools.product(*array):
        yield a

for a in iter_tools(*x):
    print(a)

相关问题 更多 >