python - 随机交错多个迭代,同时在 python 中保留它们的顺序

标签 python

灵感来自 this earlier stack overflow question我一直在考虑如何在 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 中随机交错迭代,保留元素的原始顺序,不需要提前知道迭代的长度,也不需要复制迭代?

编辑:请注意,与原始问题一样,我不需要随机化来公平。

最佳答案

这是使用生成器实现的一种方法:

import random

def interleave(*args):
  iters = map(iter, args)
  while iters:
    it = random.choice(iters)
    try:
      yield next(it)
    except StopIteration:
      iters.remove(it)

print list(interleave(xrange(1, 5), xrange(5, 10), xrange(10, 15)))

关于python - 随机交错多个迭代,同时在 python 中保留它们的顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10648331/

相关文章:

python - 如何处理 Matplotlib 中带时区的时间?

javascript - 无法使用selenium在onclick中执行javascript

python - 从文本文件中检索单个整数并将其分配给变量

python - Django - 如何按字段中的字符数对查询集进行排序

python - 通过 linux 发送格式化的 html 邮件

python - 从数组生成 Django 表单

python - 在 django View 中使用 subprocess.Popen() 执行 python 脚本

python - 将 Bokeh 服务器嵌入为库 : standalone vs. Tornado 和面向对象的设计

python - 从字符串中的字符生成像素矩阵

python - 如何在python中导入模块