假设我有两个迭代器"iter1"和"iter2":可能是一个素数生成器和itertools.count()。我预先知道它们都是无限的,并且单调递增的。现在我想要对两个参数"op"(例如operator.add或operator.mul)进行一些简单的操作,并使用该操作计算第一个迭代器的每个元素与下一个迭代器的每个元素,然后按顺序一个一个地产生它们。显然,这本身就是一个无限序列。(如@RyanThompson所述:这将被称为这些序列的笛卡尔积...或者更确切地说,是该积的一维排序。)
最好的方法是什么:
1. 将"iter1"、"iter2"和"op"封装在一个可迭代对象中,该对象本身按单调递增的输出产生值。
允许的简化假设:
1. 如果有帮助,我们可以假设op(a,b) >= a并且op(a,b) >= b。 2. 如果有帮助,我们可以假设op(a,b)>op(a,c)对所有b>c。
- 另外一种可接受的迭代器是以“一般递增”的顺序产生值的迭代器……我的意思是,可迭代对象偶尔会给我一个比上一个小的数字,但它会以某种方式提供“侧面信息”(例如通过对象上的方法),告诉我:“我不能保证我给你的下一个值将大于我刚才给你的值,但我确信所有未来的值至少都将大于N。”……而“N”本身是单调递增的。
我能想到的唯一方法是一种“对角线化”过程,在这个过程中,我会保留越来越多的部分处理的可迭代对象,并“向前看”找到所有可能的next()值中最小的那个,并产生它。但是这种奇怪的堆和一堆双端队列的聚合似乎太过离奇,甚至在我开始编码之前就已经如此。
请注意:请不要基于我的示例提到质数或count()来回答问题……我有几个非与质数和count()相关的用途,需要这个概念。
更新:哇!讨论太棒了!有些回答解释得非常透彻。非常感谢。StackOverflow很棒,你们也很棒。
我很快就会更深入地研究每个答案,并测试代码示例。从我目前阅读的内容来看,我的最初怀疑已经得到证实,即没有“简单的Python习惯用语”可以做到这一点。不管怎样,我无法避免持续保留iter1和iter2的所有产生值。
顺便说一句:如果你想尝试解决方案,这里有一个官方的“测试用例”。
import operator
def powers_of_ten():
n = 0
while True:
yield 10**n
n += 1
def series_of_nines():
yield 1
n = 1
while True:
yield int("9"*n)
n += 1
op = operator.mul
iter1 = powers_of_ten()
iter2 = series_of_nines()
# given (iter1, iter2, op), create an iterator that yields:
# [1, 9, 10, 90, 99, 100, 900, 990, 999, 1000, 9000, 9900, 9990, 9999, 10000, ...]
op
是(+)
,那么你提出的对角线算法可以奏效。另一方面,如果你与lambda *args:random.choice(args)
合并,那么你根本无法合并... 请问你的实际问题是什么? - Jochen Ritzel