【问题标题】:Yield multiple objects at a time from an iterable object?从可迭代对象一次产生多个对象?
【发布时间】:2011-01-13 05:35:59
【问题描述】:

如何从一个可迭代对象一次生成多个项目?

例如,对于任意长度的序列,我如何迭代序列中的项目,每次迭代以 X 个连续项目为一组?

【问题讨论】:

  • @Paul:不是重复的,这使用“iterable”而不是“list”,并从那里引用 Ned:“这是对问题的一个有趣的扩展,但原始问题清楚地询问了关于在列表。”
  • 以上链接中评分最高的答案与此处给出的答案相同。与其他副本的批准答案相同:stackoverflow.com/questions/434287/… 当最佳答案是从标准库复制的 4 行函数时,这个问题几乎没有什么价值。
  • 我已经看到从其他地方提取的答案在 SO 上多次具有很高的价值。在传递几个问题时提到了迭代器分组的解决方案,但没有提出与它相关的直接问题。我把这个问题放在这里纯粹是为了让下一个遇到同样问题的可怜虫立即找到正确答案。
  • 我有点粗鲁;看到别人这样在他们的问题上抹黑我的名字并不令人愉快,我不得不退后一步才能看到原因。

标签: python iterator grouping yield


【解决方案1】:

这是另一种适用于没有 izip_longest 的旧版 Python 的方法:

def grouper(n, seq):
  result = []
  for x in seq:
    result.append(x)
    if len(result) >= n:
      yield tuple(result)
      del result[:]
  if result:
    yield tuple(result)

没有填充符,所以最后一组的元素可能少于 n 个。

【讨论】:

  • 请注意itertools 中的所有函数在文档中都有纯 Python 实现,如果有人使用的 Python 版本早于 2.6。
【解决方案2】:

您的问题有点含糊,但请查看itertools 文档中的grouper 配方。

def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

(使用[iter(iterable)]*n 多次压缩同一个迭代器是一个老技巧,但是将它封装在这个函数中可以避免混淆代码,并且它与许多人将使用的完全相同的形式和接口。这是一个有点普遍的需求,它是有点遗憾,它实际上不在 itertools 模块中。)

【讨论】:

  • AFAIK [iter(iterable)]*n 很脏,因为未定义函数参数的执行顺序,即您不能确定函数的第一个参数首先得到评估。只要您使用相同的解释器,这可能不是问题,但使用其他解释器可能会产生奇怪的结果。
  • @Michael,订单有保证,看这里:docs.python.org/library/itertools.html#itertools.izip
  • @Michael,我不明白你为什么会这样想,顺序是非常明确的。
  • 对,这不是问题。我的意思是:当你写像f(3+4, 5+6) 这样的东西时,没有定义是先评估3+4 还是5+6。但这在这里不是问题,因为两个参数是相同的,iter 之前被评估过。
  • @Michael:评估顺序有保证。 f(x,y) 将始终在 y 之前评估 x。见docs.python.org/reference/expressions.html#evaluation-order
猜你喜欢
  • 2011-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多