我想创建生成器,它可以在无限的外观中连续地(连续地)合并来自iterables的值。
主要思想是,当您提出要求时,生成器每次都会将值生成到输出中。因此,主要功能是无限循环,您可以逐个询问生成器的值并将其打印到输出中。
虽然值来自迭代器,但生成器会逐个返回值以将它们打印到输出中。
现在,在我的代码中,我将值传递到一个列表中。但是在打印之前没有必要将所有值收集到一个列表中。
def merge(*iterables):
# create a generator
generator = (iter(current) for current in iterables)
# convert generator to a list
iters = list(generator)
# while we have a iterable
while iters:
#loop through each iterable
for i in iters:
try:
# yields the values one by one
yield i.__next__()
except StopIteration:
iters.remove(i)
当我这样跑:
>>> callmerge([1,5,9],[2,5],[1,6,10,11])
Result is:
[1, 1, 2, 5, 5, 6, 9, 10, 11]
要明确我有一个例子:
让我们想象一下,我们正在从几个黑盒子里拿出数字(比如宾果)。
我们真的不知道每个盒子里的球数。我们可以从盒子里一个接一个地拿球。
我们知道,来自同一个黑匣子的每一个下一个球的数量都会比以前更大。
所以,我们应该从黑匣子中取出球,并在每一步给出一个数量最小的球给我们的助手。
所以,我的问题是我如何创建生成器,它可以在无休止的外观中合并来自迭代的值(连续)? (由于记忆的原因,我也不会使用列表 - 我知道也许是itertools.chain(* iterables)是不错的选择,但不知道如何使用)
答案 0 :(得分:0)
我认为这是itertools(Python3,Python2)的任务。实施例
from itertools import chain
list(chain.from_iterable(([1,5,9],[2,5],[1,6,10,11])))
[1, 5, 9, 2, 5, 1, 6, 10, 11]
如果您需要它们,您可以在列表
上应用sorted
sorted(list(chain.from_iterable(([1,5,9],[2,5],[1,6,10,11]))))
来自docs:
创建一个迭代器,返回第一个iterable中的元素,直到 它耗尽,然后进入下一个迭代,直到所有的 迭代用尽了。用于处理连续序列 单一序列
答案 1 :(得分:0)
def get_vals(*iterables):
vals = []
for it in iterables:
try:
vals.append(next(it))
except StopIteration:
vals.append(None) #Keep indices the same
return vals
def sort_merge(*iterables):
iterables = [iter(it) for it in iterables]
vals = get_vals(*iterables)
while any(v is not None for v in vals):
i, m = min(filter(lambda x: x[1] is not None, enumerate(vals)), key=lambda x: x[1])
yield m
try:
vals[i] = next(iterables[i])
except StopIteration:
vals[i] = None
您必须实际比较这些值才能对它们进行排序。我不确定这会比仅仅sorted(itertools.chain(...))
给你带来任何真正的好处,但这只会在任何给定时间内将len(iterables)
个项目保留在内存中。
编辑:要使此(或任何其他迭代器)重复无限期地使用itertools.cycle
itertools.cycle(sort_merge([1,5,9],[2,5],[1,6,10,11]))
答案 2 :(得分:0)
如果我正确理解了我认为你之后的事情itertools.chain
Python 3,Python 2允许你将可迭代组合在一起。
def merge(*iterables):
for i, inner in enumerate(iterables):
for j, item in enumerate(inner):
yield i, j, item
# Test Data
x = merge(list(range(3)), list(range(3, 5)))
y = merge(list(range(5, 7)), list(range(8, 10)))
for item in x:
print(item)
for item in y:
print(item)
# Output
(0, 0, 0)
(0, 1, 1)
(0, 2, 2)
(1, 0, 3)
(1, 1, 4)
(0, 0, 5)
(0, 1, 6)
(1, 0, 8)
(1, 1, 9)
然后组合两个或更多发电机。
z = itertools.chain(x, y)
for item in z:
print(item)
# Output
(0, 0, 0)
(0, 1, 1)
(0, 2, 2)
(1, 0, 3)
(1, 1, 4)
(0, 0, 5)
(0, 1, 6)
(1, 0, 8)
(1, 1, 9)
如果你想用它进行分类,那么我就有了这个解决方案,但是我无法保证它的效率,我还没有定时(因为我没有任何东西要比较它)但我觉得多次list
次调用可能不适合真正的大型迭代。
def sort(*iterables):
while True:
lst = list(merge(*iterables))
if not lst:
return
i, j, v = min(lst, key = lambda tup: tup[2])
yield iterables[i].pop(j)
>>> list(sort([1,5,9],[2,5],[1,6,10,11]))
[1, 1, 2, 5, 5, 6, 9, 10, 11]
如果你想让它无限期地继续,那么itertools.cycle
是一个无限的生成器,在到达结束后循环回到开始。