Python中Ruby的each_slice(count)的等价实现

13 投票
6 回答
3474 浏览
提问于 2025-04-16 04:49

Python中有没有类似于Ruby的each_slice(count)的功能?
我想在每次循环中从列表中取出2个元素。
比如对于[1,2,3,4,5,6],我想在第一次循环中处理1,2,然后是3,4,接着是5,6
当然可以通过索引值来实现这个功能,但有没有更直接的函数或者方法可以做到这一点呢?

6 个回答

4

这个内容是说,有一种方法可以模仿Ruby语言中的each_slice功能,特别是处理最后一小部分数据的时候。

def each_slice(size, iterable):
    """ Chunks the iterable into size elements at a time, each yielded as a list.

    Example:
      for chunk in each_slice(2, [1,2,3,4,5]):
          print(chunk)

      # output:
      [1, 2]
      [3, 4]
      [5]
    """
    current_slice = []
    for item in iterable:
        current_slice.append(item)
        if len(current_slice) >= size:
            yield current_slice
            current_slice = []
    if current_slice:
        yield current_slice

上面提到的答案会在最后的列表中添加一些填充内容(比如说[5, None]),但在某些情况下,这可能不是你想要的结果。

5

我知道这个问题已经有很多语言专家回答过了,但我有一个不同的方法,使用生成器函数,这样更容易理解、阅读和根据你的需求进行修改:

def each_slice(list: List[str], size: int):
    batch = 0
    while batch * size < len(list):
        yield list[batch * size:(batch + 1) * size]
        batch += 1   

slices = each_slice(["a", "b", "c", "d", "e", "f", "g"], 2)
print([s for s in slices])

$ [['a', 'b'], ['c', 'd'], ['e', 'f'], ['g']]

如果你需要每一片的大小是固定的批量大小,你可以简单地在生成的结果中添加一些填充,比如填充None或者其他默认字符。如果你想要的是每次只取一个元素,可以通过修改代码,让它一个一个地移动,而不是一次性处理一批。

10

itertools 文档 中,有一个叫做 grouper 的 示例,可以用来解决这个问题:

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

使用方法如下:

>>> l = [1,2,3,4,5,6]
>>> for a,b in grouper(2, l):
>>>     print a, b

1 2
3 4
5 6

撰写回答