如何分块迭代列表

2024-11-19 08:38:00
admin
原创
9
摘要:问题描述:我有一个 Python 脚本,它以整数列表作为输入,我需要一次处理四个整数。不幸的是,我无法控制输入,否则我会将其作为四元素元组列表传入。目前,我以这种方式对其进行迭代:for i in range(0, len(ints), 4): # dummy op for example code ...

问题描述:

我有一个 Python 脚本,它以整数列表作为输入,我需要一次处理四个整数。不幸的是,我无法控制输入,否则我会将其作为四元素元组列表传入。目前,我以这种方式对其进行迭代:

for i in range(0, len(ints), 4):
    # dummy op for example code
    foo += ints[i] * ints[i + 1] + ints[i + 2] * ints[i + 3]

不过,它看起来很像“C-think”,这让我怀疑有一种更符合 Python 的方式来处理这种情况。列表在迭代后被丢弃,因此不需要保留。也许像这样的东西会更好?

while ints:
    foo += ints[0] * ints[1] + ints[2] * ints[3]
    ints[0:4] = []

但仍然感觉不太对劲。:-/

更新:随着 Python 3.12 的发布,我更改了可接受的答案。对于尚未(或无法)升级到 Python 3.12 的任何人,我鼓励您查看之前可接受的答案或下面任何其他出色的向后兼容答案。

相关问题:在 Python 中,如何将列表分成大小均匀的块?


解决方案 1:

def chunker(seq, size):
    return (seq[pos:pos + size] for pos in range(0, len(seq), size))

适用于任意序列:

text = "I am a very, very helpful text"

for group in chunker(text, 7):
   print(repr(group),)
# 'I am a ' 'very, v' 'ery hel' 'pful te' 'xt'

print('|'.join(chunker(text, 10)))
# I am a ver|y, very he|lpful text

animals = ['cat', 'dog', 'rabbit', 'duck', 'bird', 'cow', 'gnu', 'fish']

for group in chunker(animals, 3):
    print(group)
# ['cat', 'dog', 'rabbit']
# ['duck', 'bird', 'cow']
# ['gnu', 'fish']

解决方案 2:

从Python 文档的Recipesitertools部分修改而来:

from itertools import zip_longest

def grouper(iterable, n, fillvalue=None):
    args = [iter(iterable)] * n
    return zip_longest(*args, fillvalue=fillvalue)

例子

grouper('ABCDEFGHIJ', 3, 'x')  # --> 'ABC' 'DEF' 'GHI' 'Jxx'

注意:在 Python 2 上使用izip_longest而不是zip_longest

解决方案 3:

chunk_size = 4
for i in range(0, len(ints), chunk_size):
    chunk = ints[i:i+chunk_size]
    # process chunk of size <= chunk_size

解决方案 4:

自 Python 3.8 起,您可以使用海象:=运算符和itertools.islice

from itertools import islice

list_ = [i for i in range(10, 100)]

def chunker(it, size):
    iterator = iter(it)
    while chunk := list(islice(iterator, size)):
        print(chunk)
In [2]: chunker(list_, 10)                                                         
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
[30, 31, 32, 33, 34, 35, 36, 37, 38, 39]
[40, 41, 42, 43, 44, 45, 46, 47, 48, 49]
[50, 51, 52, 53, 54, 55, 56, 57, 58, 59]
[60, 61, 62, 63, 64, 65, 66, 67, 68, 69]
[70, 71, 72, 73, 74, 75, 76, 77, 78, 79]
[80, 81, 82, 83, 84, 85, 86, 87, 88, 89]
[90, 91, 92, 93, 94, 95, 96, 97, 98, 99]

解决方案 5:

import itertools
def chunks(iterable,size):
    it = iter(iterable)
    chunk = tuple(itertools.islice(it,size))
    while chunk:
        yield chunk
        chunk = tuple(itertools.islice(it,size))

# though this will throw ValueError if the length of ints
# isn't a multiple of four:
for x1,x2,x3,x4 in chunks(ints,4):
    foo += x1 + x2 + x3 + x4

for chunk in chunks(ints,4):
    foo += sum(chunk)

另一种方法:

import itertools
def chunks2(iterable,size,filler=None):
    it = itertools.chain(iterable,itertools.repeat(filler,size-1))
    chunk = tuple(itertools.islice(it,size))
    while len(chunk) == size:
        yield chunk
        chunk = tuple(itertools.islice(it,size))

# x2, x3 and x4 could get the value 0 if the length is not
# a multiple of 4.
for x1,x2,x3,x4 in chunks2(ints,4,0):
    foo += x1 + x2 + x3 + x4

解决方案 6:

如果您不介意使用外部包,可以使用iteration_utilities.grouperfrom 1。它支持所有可迭代对象(不仅仅是序列):iteration_utilties

from iteration_utilities import grouper
seq = list(range(20))
for group in grouper(seq, 4):
    print(group)

打印结果为:

(0, 1, 2, 3)
(4, 5, 6, 7)
(8, 9, 10, 11)
(12, 13, 14, 15)
(16, 17, 18, 19)

如果长度不是组大小的倍数,它还支持填充(不完整的最后一个组)或截断(丢弃不完整的最后一个组)最后一个组:

from iteration_utilities import grouper
seq = list(range(17))
for group in grouper(seq, 4):
    print(group)
# (0, 1, 2, 3)
# (4, 5, 6, 7)
# (8, 9, 10, 11)
# (12, 13, 14, 15)
# (16,)

for group in grouper(seq, 4, fillvalue=None):
    print(group)
# (0, 1, 2, 3)
# (4, 5, 6, 7)
# (8, 9, 10, 11)
# (12, 13, 14, 15)
# (16, None, None, None)

for group in grouper(seq, 4, truncate=True):
    print(group)
# (0, 1, 2, 3)
# (4, 5, 6, 7)
# (8, 9, 10, 11)
# (12, 13, 14, 15)

基准

我还决定比较上述几种方法的运行时间。这是一个对数对数图,根据不同大小的列表将元素分组为“10”个组。对于定性结果:越低意味着越快:

在此处输入图片描述

至少在这个基准测试中,表现最好。其次是Craziteration_utilities.grouper的方法。

基准测试是用1创建的。运行此基准测试所用的代码是:simple_benchmark

import iteration_utilities
import itertools
from itertools import zip_longest

def consume_all(it):
    return iteration_utilities.consume(it, None)

import simple_benchmark
b = simple_benchmark.BenchmarkBuilder()

@b.add_function()
def grouper(l, n):
    return consume_all(iteration_utilities.grouper(l, n))

def Craz_inner(iterable, n, fillvalue=None):
    args = [iter(iterable)] * n
    return zip_longest(*args, fillvalue=fillvalue)

@b.add_function()
def Craz(iterable, n, fillvalue=None):
    return consume_all(Craz_inner(iterable, n, fillvalue))

def nosklo_inner(seq, size):
    return (seq[pos:pos + size] for pos in range(0, len(seq), size))

@b.add_function()
def nosklo(seq, size):
    return consume_all(nosklo_inner(seq, size))

def SLott_inner(ints, chunk_size):
    for i in range(0, len(ints), chunk_size):
        yield ints[i:i+chunk_size]

@b.add_function()
def SLott(ints, chunk_size):
    return consume_all(SLott_inner(ints, chunk_size))

def MarkusJarderot1_inner(iterable,size):
    it = iter(iterable)
    chunk = tuple(itertools.islice(it,size))
    while chunk:
        yield chunk
        chunk = tuple(itertools.islice(it,size))

@b.add_function()
def MarkusJarderot1(iterable,size):
    return consume_all(MarkusJarderot1_inner(iterable,size))

def MarkusJarderot2_inner(iterable,size,filler=None):
    it = itertools.chain(iterable,itertools.repeat(filler,size-1))
    chunk = tuple(itertools.islice(it,size))
    while len(chunk) == size:
        yield chunk
        chunk = tuple(itertools.islice(it,size))

@b.add_function()
def MarkusJarderot2(iterable,size):
    return consume_all(MarkusJarderot2_inner(iterable,size))

@b.add_arguments()
def argument_provider():
    for exp in range(2, 20):
        size = 2**exp
        yield size, simple_benchmark.MultiArgument([[0] * size, 10])

r = b.run()

1iteration_utilities免责声明:我是该库和的作者simple_benchmark

解决方案 7:

从 Python 3.12 开始,该itertools模块获得了一个batched函数,专门涵盖对输入可迭代对象的批次进行迭代,其中最终批次可能不完整(每个批次都是tuple)。根据文档中给出的示例代码:

>>> for batch in batched('ABCDEFG', 3):
...     print(batch)
...
('A', 'B', 'C')
('D', 'E', 'F')
('G',)

性能说明:

batched`itertools`与迄今为止的所有函数一样,的实现是在 C 层,因此它能够进行 Python 级代码无法比拟的优化,例如

  • 在每次提取新批次时,它都会主动分配一个tuple精确正确大小的(除最后一批外的所有批次),而不是逐个元素地构建摊销增长,从而导致多次重新分配(调用的tuple解决方案的方式)tuple`islice`

  • 它只需要每批次查找.__next__一次底层迭代器的函数,而不是n每批次查找多次(zip_longest((iter(iterable),) * n)基于 - 的方法)

  • 对最终情况的检查是一个简单的 C 级NULL检查(很简单,而且无论如何都需要处理可能的异常)

  • 处理最终情况是 Cgoto后跟直接realloc(不复制到较小的tuple)直到已知的最终大小,因为它跟踪它成功拉取了多少个元素(没有复杂的“创建哨兵以供使用并对每个批次fillvalue执行 Python 级别if/else检查以查看它是否为空,最后一批需要搜索fillvalue最后出现的位置,以创建基于的解决方案所需的削减tuplezip_longest)。

在所有这些优势之间,它应该大大胜过任何 Python 级别的解决方案(即使是高度优化的解决方案,将大多数或所有每个项目的工作推送到 C 层),无论输入的可迭代对象是长还是短,也无论批次大小和最终(可能不完整)批次的大小如何(zip_longest基于保证唯一fillvalues 的安全性的itertools.batched解决方案在几乎所有不可用的情况下都是最好的解决方案,但它们可能会在“少数大批次,最终批次大部分但未完全填充”的病态情况下受到影响,尤其是在 3.10 之前,bisect不能用于优化将fillvalues 从O(n)线性搜索切分为O(log n)二进制搜索,但batched完全避免了该搜索,因此它根本不会遇到病态情况)。

解决方案 8:

我需要一个可以与集合和生成器配合使用的解决方案。我无法想出任何非常简短和漂亮的解决方案,但至少它具有可读性。

def chunker(seq, size):
    res = []
    for el in seq:
        res.append(el)
        if len(res) == size:
            yield res
            res = []
    if res:
        yield res

列表:

>>> list(chunker([i for i in range(10)], 3))
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]

放:

>>> list(chunker(set([i for i in range(10)]), 3))
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]

发电机:

>>> list(chunker((i for i in range(10)), 3))
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]

解决方案 9:

more-itertools包中有一个chunked方法,它的作用正是如此:

import more_itertools
for s in more_itertools.chunked(range(9), 4):
    print(s)

印刷

[0, 1, 2, 3]
[4, 5, 6, 7]
[8]

chunked返回列表中的项目。如果您更喜欢可迭代对象,请使用ichunked。

解决方案 10:

这个问题的理想解决方案是使用迭代器(而不仅仅是序列)。它也应该很快。

这是 itertools 文档提供的解决方案:

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

在我的 mac book air 上使用 ipython %timeit,每个循环得到 47.5 us。

但是,这对我来说真的不起作用,因为结果被填充为均等大小的组。没有填充的解决方案稍微复杂一些。最简单的解决方案可能是:

def grouper(size, iterable):
    i = iter(iterable)
    while True:
        out = []
        try:
            for _ in range(size):
                out.append(i.next())
        except StopIteration:
            yield out
            break
        
        yield out

简单,但速度很慢:每循环 693 微秒

我能想到的最佳解决方案islice是使用内循环:

def grouper(size, iterable):
    it = iter(iterable)
    while True:
        group = tuple(itertools.islice(it, None, size))
        if not group:
            break
        yield group

使用相同的数据集,我每循环得到 305 us。

由于无法更快地获得纯解决方案,我提供了以下解决方案,但有一个重要的警告:如果您的输入数据filldata中包含实例,则可能会得到错误的答案。

def grouper(n, iterable, fillvalue=None):
    #"grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    # itertools.zip_longest on Python 3
    for x in itertools.izip_longest(*args, fillvalue=fillvalue):
        if x[-1] is fillvalue:
            yield tuple(v for v in x if v is not fillvalue)
        else:
            yield x

我真的不喜欢这个答案,但它的速度明显更快。每循环 124 微秒

解决方案 11:

from itertools import izip_longest

def chunker(iterable, chunksize, filler):
    return izip_longest(*[iter(iterable)]*chunksize, fillvalue=filler)

解决方案 12:

由于还没有人提到它,所以这里有一个zip()解决方案:

>>> def chunker(iterable, chunksize):
...     return zip(*[iter(iterable)]*chunksize)

仅当序列的长度始终可以被块大小整除时它才有效,或者如果不是,您不关心尾随的块。

例子:

>>> s = '1234567890'
>>> chunker(s, 3)
[('1', '2', '3'), ('4', '5', '6'), ('7', '8', '9')]
>>> chunker(s, 4)
[('1', '2', '3', '4'), ('5', '6', '7', '8')]
>>> chunker(s, 5)
[('1', '2', '3', '4', '5'), ('6', '7', '8', '9', '0')]

或者使用itertools.izip返回迭代器而不是列表:

>>> from itertools import izip
>>> def chunker(iterable, chunksize):
...     return izip(*[iter(iterable)]*chunksize)

可以使用@ΤΖΩΤΖΙΟΥ 的答案来修复填充:

>>> from itertools import chain, izip, repeat
>>> def chunker(iterable, chunksize, fillvalue=None):
...     it   = chain(iterable, repeat(fillvalue, chunksize-1))
...     args = [it] * chunksize
...     return izip(*args)

解决方案 13:

与其他提案类似,但并不完全相同,我喜欢这样做,因为它简单易读:

it = iter([1, 2, 3, 4, 5, 6, 7, 8, 9])
for chunk in zip(it, it, it, it):
    print chunk

>>> (1, 2, 3, 4)
>>> (5, 6, 7, 8)

这样你就不会得到最后一部分块。如果你想要获取(9, None, None, None)最后一块,只需使用izip_longestfrom itertools

解决方案 14:

另一种方法是使用双参数形式iter

from itertools import islice

def group(it, size):
    it = iter(it)
    return iter(lambda: tuple(islice(it, size)), ())

这可以很容易地适应使用填充(这类似于Markus Jarderot的答案):

from itertools import islice, chain, repeat

def group_pad(it, size, pad=None):
    it = chain(iter(it), repeat(pad))
    return iter(lambda: tuple(islice(it, size)), (pad,) * size)

这些甚至可以组合起来用于可选的填充:

_no_pad = object()
def group(it, size, pad=_no_pad):
    if pad == _no_pad:
        it = iter(it)
        sentinel = ()
    else:
        it = chain(iter(it), repeat(pad))
        sentinel = (pad,) * size
    return iter(lambda: tuple(islice(it, size)), sentinel)

解决方案 15:

如果列表很大,那么性能最高的方法是使用生成器:

def get_chunk(iterable, chunk_size):
    result = []
    for item in iterable:
        result.append(item)
        if len(result) == chunk_size:
            yield tuple(result)
            result = []
    if len(result) > 0:
        yield tuple(result)

for x in get_chunk([1,2,3,4,5,6,7,8,9,10], 3):
    print x

(1, 2, 3)
(4, 5, 6)
(7, 8, 9)
(10,)

解决方案 16:

使用小函数和小东西确实对我没有吸引力;我更喜欢使用切片:

data = [...]
chunk_size = 10000 # or whatever
chunks = [data[i:i+chunk_size] for i in xrange(0,len(data),chunk_size)]
for chunk in chunks:
    ...

解决方案 17:

使用 map() 而不是 zip() 修复了 JF Sebastian 的答案中的填充问题:

>>> def chunker(iterable, chunksize):
...   return map(None,*[iter(iterable)]*chunksize)

例子:

>>> s = '1234567890'
>>> chunker(s, 3)
[('1', '2', '3'), ('4', '5', '6'), ('7', '8', '9'), ('0', None, None)]
>>> chunker(s, 4)
[('1', '2', '3', '4'), ('5', '6', '7', '8'), ('9', '0', None, None)]
>>> chunker(s, 5)
[('1', '2', '3', '4', '5'), ('6', '7', '8', '9', '0')]

解决方案 18:

单行、临时解决方案,用于按x大小块迭代列表4-

for a, b, c, d in zip(x[0::4], x[1::4], x[2::4], x[3::4]):
    ... do something with a, b, c and d ...

解决方案 19:

为了避免所有转换为列表import itertools

>>> for k, g in itertools.groupby(xrange(35), lambda x: x/10):
...     list(g)

生成:

... 
0 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1 [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
2 [20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
3 [30, 31, 32, 33, 34]
>>> 

我检查了一下groupby,它不会转换为列表或使用,len所以我(认为)这会延迟每个值的解析,直到实际使用为止。遗憾的是,目前似乎没有可用的答案提供这种变体。

显然,如果您需要依次处理每个项目,则对 g 进行嵌套 for 循环:

for k,g in itertools.groupby(xrange(35), lambda x: x/10):
    for i in g:
       # do what you need to do with individual items
    # now do what you need to do with the whole group

我对此特别感兴趣的是需要使用一个生成器向 gmail API 批量提交最多 1000 个更改:

    messages = a_generator_which_would_not_be_smart_as_a_list
    for idx, batch in groupby(messages, lambda x: x/1000):
        batch_request = BatchHttpRequest()
        for message in batch:
            batch_request.add(self.service.users().messages().modify(userId='me', id=message['id'], body=msg_labels))
        http = httplib2.Http()
        self.credentials.authorize(http)
        batch_request.execute(http=http)

解决方案 20:

除非我错过了什么,否则下面这个使用生成器表达式的简单解决方案还没有被提及。它假设块的大小和数量都是已知的(通常是这种情况),并且不需要填充:

def chunks(it, n, m):
    """Make an iterator over m first chunks of size n.
    """
    it = iter(it)
    # Chunks are presented as tuples.
    return (tuple(next(it) for _ in range(n)) for _ in range(m))

解决方案 21:

在你的第二种方法中,我将通过执行以下操作进入下一组 4 个:

ints = ints[4:]

但是,我还没有做过任何性能测量,所以我不知道哪一个可能更有效率。

话虽如此,我通常会选择第一种方法。这种方法不太好,但这通常是与外界交互的结果。

解决方案 22:

使用 NumPy 很简单:

ints = array([1, 2, 3, 4, 5, 6, 7, 8])
for int1, int2 in ints.reshape(-1, 2):
    print(int1, int2)

输出:

1 2
3 4
5 6
7 8

解决方案 23:

我从来不想让我的块被填充,所以这个要求是必不可少的。我发现处理任何可迭代对象的能力也是必需的。鉴于此,我决定扩展已接受的答案,https://stackoverflow.com/a/434411/1074659

如果不需要填充,则此方法的性能会略有下降,因为需要比较和过滤填充值。但是,对于较大的块大小,此实用程序的性能非常高。

#!/usr/bin/env python3
from itertools import zip_longest


_UNDEFINED = object()


def chunker(iterable, chunksize, fillvalue=_UNDEFINED):
    """
    Collect data into chunks and optionally pad it.

    Performance worsens as `chunksize` approaches 1.

    Inspired by:
        https://docs.python.org/3/library/itertools.html#itertools-recipes

    """
    args = [iter(iterable)] * chunksize
    chunks = zip_longest(*args, fillvalue=fillvalue)
    yield from (
        filter(lambda val: val is not _UNDEFINED, chunk)
        if chunk[-1] is _UNDEFINED
        else chunk
        for chunk in chunks
    ) if fillvalue is _UNDEFINED else chunks

解决方案 24:

def chunker(iterable, n):
    """Yield iterable in chunk sizes.

    >>> chunks = chunker('ABCDEF', n=4)
    >>> chunks.next()
    ['A', 'B', 'C', 'D']
    >>> chunks.next()
    ['E', 'F']
    """
    it = iter(iterable)
    while True:
        chunk = []
        for i in range(n):
            try:
                chunk.append(next(it))
            except StopIteration:
                yield chunk
                raise StopIteration
        yield chunk

if __name__ == '__main__':
    import doctest

    doctest.testmod()

解决方案 25:

还有另一种答案,其优点是:

1)易于理解

2)适用于任何可迭代对象,而不仅仅是序列(上述某些答案会阻塞文件句柄)

3)不会一次将块全部加载到内存中

4)不会在内存中创建对同一迭代器的块长引用列表

5)列表末尾没有填充值

话虽如此,我还没有计时,所以它可能比一些更聪明的方法慢,并且一些优势可能与用例无关。

def chunkiter(iterable, size):
  def inneriter(first, iterator, size):
    yield first
    for _ in xrange(size - 1): 
      yield iterator.next()
  it = iter(iterable)
  while True:
    yield inneriter(it.next(), it, size)

In [2]: i = chunkiter('abcdefgh', 3)
In [3]: for ii in i:                                                
          for c in ii:
            print c,
          print ''
        ...:     
        a b c 
        d e f 
        g h 

更新:

由于内循环和外循环都从同一个迭代器中提取值,因此存在一些缺点:

1) continue 在外循环中无法按预期工作 - 它只是继续执行下一个项目,而不是跳过一个块。但是,这似乎不是一个问题,因为外循环中没有什么可测试的。2

) break 在内循环中无法按预期工作 - 控制将再次在内循环中结束,迭代器中还有下一个项目。要跳过整个块,可以将内部迭代器(上面的 ii)包装在元组中,例如for c in tuple(ii),或者设置一个标志并耗尽迭代器。

解决方案 26:

def group_by(iterable, size):
    """Group an iterable into lists that don't exceed the size given.

    >>> group_by([1,2,3,4,5], 2)
    [[1, 2], [3, 4], [5]]

    """
    sublist = []

    for index, item in enumerate(iterable):
        if index > 0 and index % size == 0:
            yield sublist
            sublist = []

        sublist.append(item)

    if sublist:
        yield sublist

解决方案 27:

您可以使用funcy库中的分区或块函数:

from funcy import partition

for a, b, c, d in partition(4, ints):
    foo += a * b * c * d

这些函数还具有迭代器版本ipartitionichunks,在这种情况下会更有效率。

您还可以了解它们的实现情况。

解决方案 28:

J.F. Sebastian 关于这里给出的解决方案:

def chunker(iterable, chunksize):
    return zip(*[iter(iterable)]*chunksize)

它很聪明,但有一个缺点 - 总是返回元组。如何获取字符串?

当然你可以写''.join(chunker(...)),但无论如何都会构造临时元组。

您可以通过编写 own 来摆脱临时元组zip,如下所示:

class IteratorExhausted(Exception):
    pass

def translate_StopIteration(iterable, to=IteratorExhausted):
    for i in iterable:
        yield i
    raise to # StopIteration would get ignored because this is generator,
             # but custom exception can leave the generator.

def custom_zip(*iterables, reductor=tuple):
    iterators = tuple(map(translate_StopIteration, iterables))
    while True:
        try:
            yield reductor(next(i) for i in iterators)
        except IteratorExhausted: # when any of iterators get exhausted.
            break

然后

def chunker(data, size, reductor=tuple):
    return custom_zip(*[iter(data)]*size, reductor=reductor)

使用示例:

>>> for i in chunker('12345', 2):
...     print(repr(i))
...
('1', '2')
('3', '4')
>>> for i in chunker('12345', 2, ''.join):
...     print(repr(i))
...
'12'
'34'

解决方案 29:

我喜欢这种方法。它感觉简单但并不神奇,并且支持所有可迭代类型,并且不需要导入。

def chunk_iter(iterable, chunk_size):
it = iter(iterable)
while True:
    chunk = tuple(next(it) for _ in range(chunk_size))
    if not chunk:
        break
    yield chunk

解决方案 30:

这里非常具有 Python 风格(您也可以内联函数主体split_groups

import itertools
def split_groups(iter_in, group_size):
    return ((x for _, x in item) for _, item in itertools.groupby(enumerate(iter_in), key=lambda x: x[0] // group_size))

for x, y, z, w in split_groups(range(16), 4):
    foo += x * y + z * w
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用