Python 当两个不可数中的一个无穷大时,如何得到它们的笛卡尔积
假设我有两个可数,一个是有限的,一个是无限的:Python 当两个不可数中的一个无穷大时,如何得到它们的笛卡尔积,python,itertools,cartesian-product,Python,Itertools,Cartesian Product,假设我有两个可数,一个是有限的,一个是无限的: import itertools teams = ['A', 'B', 'C'] steps = itertools.count(0, 100) 我想知道是否可以避免嵌套for循环,使用模块中的一个无限迭代器,如cycle或repeat来获得这些iterables的笛卡尔积 循环应该是无限的,因为步骤的停止值在前面是未知的。 预期产出: $ python3 test.py A 0 B 0 C 0 A 100 B 100 C 100 A 20
import itertools
teams = ['A', 'B', 'C']
steps = itertools.count(0, 100)
我想知道是否可以避免嵌套for循环,使用模块中的一个无限迭代器,如cycle
或repeat
来获得这些iterables的笛卡尔积
循环应该是无限的,因为步骤的停止值在前面是未知的。
预期产出:
$ python3 test.py
A 0
B 0
C 0
A 100
B 100
C 100
A 200
B 200
C 200
etc...
使用嵌套循环的工作代码:
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()
试一试
正如文档所说,产品(A,B)
相当于((x,y)代表A中的x代表B中的y)
。
如您所见,product
生成一个元组,这意味着它是一个生成器,不在内存中创建列表以正常工作
此函数大致相当于以下代码,但实际实现不会在内存中建立中间结果:
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
用于无限循环,因为:
根据文档,itertools.product相当于
在生成器表达式中嵌套for循环。但是
itertools.product(itertools.count(2010))不是
导入itertools
>>>(itertools.count(2010年)中的年复一年)
>>>itertools.产品(itertools.计数(2010))
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
记忆者
itertools.product的输入必须是有限的
不可抗力
对于无限循环,您可以使用。有一种不使用嵌套循环的方法。基于此,您可以编写以下内容:
from itertools import count, chain, cycle, tee
teams = ['A', 'B', 'C']
steps = count(0, 100)
for team, step in zip(cycle(teams), chain.from_iterable(zip(*tee(steps, len(teams))))):
if step == 300:
break
print(team, step)
这将给出预期的输出:
$ python3 test.py
A 0
B 0
C 0
A 100
B 100
C 100
A 200
B 200
C 200
etc...
A 0
B 0
c0
100英镑
B 100
C100
200美元
B200
C 200
它完成了任务,但可读性要差得多。你能澄清一下你是如何知道何时打破无限循环的吗?当然,“步骤”(偏移量)用于在URL中同时对不同的团队进行API调用,一旦有效负载中的值指示没有“下一个”URL,对于特定团队跳过循环,如果所有团队都是这样,则代码将中断循环。这是一种解决方法,可以使用asyncio并行发出请求,否则每个请求都必须等待来自负载的下一个URL,从而导致按顺序运行。相关:@Georgy您的编辑很好,但接受的答案仅适用于有限iterable。这个问题的答案是有限可数的,如果需要无限可数的问题,应该再问一个问题@DorianTurba我不认为这是一个“变色龙问题”。IIUC,这个问题的第一个版本已经有了无限迭代器的要求,但是,它的表述不够清楚。OP的编辑(第3版)只是明确了这一点。我知道之后的回滚是错误的。
from itertools import count, chain, cycle, tee
teams = ['A', 'B', 'C']
steps = count(0, 100)
for team, step in zip(cycle(teams), chain.from_iterable(zip(*tee(steps, len(teams))))):
if step == 300:
break
print(team, step)