受这个较早的堆栈溢出问题的启发,我一直在考虑如何在 python 中随机交错可迭代对象,同时保留每个可迭代对象中元素的顺序。例如:
>>> def interleave(*iterables):
... "Return the source iterables randomly interleaved"
... <insert magic here>
>>> interleave(xrange(1, 5), xrange(5, 10), xrange(10, 15))
[1, 5, 10, 11, 2, 6, 3, 12, 4, 13, 7, 14, 8, 9]
最初的问题要求随机交错两个列表 a 和 b,并且接受的解决方案是:
>>> c = [x.pop(0) for x in random.sample([a]*len(a) + [b]*len(b), len(a)+len(b))]
但是,此解决方案仅适用于两个列表(尽管可以轻松扩展),并且依赖于 a 和 b 是列表的事实,因此pop()
可以len()
在它们上调用,这意味着它不能与可迭代对象一起使用。它还具有清空源列表 a 和 b 的不幸副作用。
为原始问题给出的替代答案会复制源列表以避免修改它们,但这让我觉得效率低下,尤其是在源列表很大的情况下。替代答案也使用,len()
因此不能仅用于可迭代对象。
我编写了自己的解决方案,适用于任意数量的输入列表并且不修改它们:
def interleave(*args):
iters = [i for i, b in ((iter(a), a) for a in args) for _ in xrange(len(b))]
random.shuffle(iters)
return map(next, iters)
但是此解决方案还依赖于作为列表的源参数,以便len()
可以在它们上使用。
那么,有没有一种有效的方法可以在 python 中随机交错迭代,保留元素的原始顺序,这不需要提前知道迭代的长度并且不需要复制迭代?
编辑:请注意,与原始问题一样,我不需要随机化是公平的。