我不确定发生了什么,但我认为每个人都有点偏离正确方向。我会归咎于我没有很好地解释我要解决的问题。无论如何,这是我已经得到的进展:
items[min(range(len(items)), key = lambda x: items[x][0][0])][0].pop(0)
这让我完成了大部分工作,但还需要处理的是当一个列表已经用尽时的情况。一旦处理好了,将其放入循环中并在其中进行yield就可以轻松地将其变成生成器,而且希望不需要太多的工作就可以将其改进为在生成器上执行高效的排序合并。
>>> items[min(range(len(items)), key = lambda x: items[x][0][0])][0].pop(0)
[0, 1]
>>> items[min(range(len(items)), key = lambda x: items[x][0][0])][0].pop(0)
[1, 3]
>>> items[min(range(len(items)), key = lambda x: items[x][0][0])][0].pop(0)
[2, 20]
>>> items[min(range(len(items)), key = lambda x: items[x][0][0])][0].pop(0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <lambda>
IndexError: list index out of range
更新:
将仍然有效的项目的适当子集组装到要进行min
操作的对象中是关键。
def next_value_in_sections(sections):
while 1:
idxs = []
for i, x in enumerate(sections):
if x[0]:
idxs.append(i)
print idxs
if not idxs:
break
j = min(idxs, key=lambda x: sections[x][0][0])
yield (sections[j][0].pop(0), j)
items = [([[0, 1], [2, 20]], 'zz', ''),
([[1, 3], [5, 29], [50, 500]], 'a', 'b')]
x = next_value_in_sections(items)
for i in x:
print i
已执行:
$ python test.py
[0, 1]
([0, 1], 0)
[0, 1]
([1, 3], 1)
[0, 1]
([2, 20], 0)
[1]
([5, 29], 1)
[1]
([50, 500], 1)
[]
我注意到这个还有改进的空间,每次迭代都会重建idxs列表。它并不需要这样做,但是这样做并不能提高渐进界。当然,我们必须想知道是否真的关心性能,无论使用lambda是否是一个好主意,尽管我真的看不到除了拆开min
之外还有其他的解决方案,那只是一种走向疯狂的行为。
mergeiter
函数;我使用enumerate()
添加索引。 - Martijn Pietersmergeiter
函数有些困惑。但在查看了其他答案后,你的方法显然是正确的。然而,这是唯一一个没有作为答案发布的方法... - Steven Lu