如何在常量大小的块中拆分迭代[重复]

时间:2021-11-18 02:08:37

Possible Duplicate:
How do you split a list into evenly sized chunks in Python?

可能重复:如何在Python中将列表拆分为大小均匀的块?

I am surprised I could not find a "batch" function that would take as input an iterable and return an iterable of iterables.

我很惊讶我找不到一个“批处理”函数,它将输入迭代并返回一个可迭代的迭代。

For example:

例如:

for i in batch(range(0,10), 1): print i
[0]
[1]
...
[9]

or:

要么:

for i in batch(range(0,10), 3): print i
[0,1,2]
[3,4,5]
[6,7,8]
[9]

Now, I wrote what I thought was a pretty simple generator:

现在,我写了一个我认为非常简单的生成器:

def batch(iterable, n = 1):
   current_batch = []
   for item in iterable:
       current_batch.append(item)
       if len(current_batch) == n:
           yield current_batch
           current_batch = []
   if current_batch:
       yield current_batch

But the above does not give me what I would have expected:

但上面没有给我我所期望的:

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

So, I have missed something and this probably shows my complete lack of understanding of python generators. Anyone would care to point me in the right direction ?

所以,我错过了一些东西,这可能表明我完全缺乏对python生成器的理解。有人会关心我指向正确的方向吗?

[Edit: I eventually realized that the above behavior happens only when I run this within ipython rather than python itself]

[编辑:我最终意识到只有当我在ipython而不是python本身中运行时才会发生上述行为]

4 个解决方案

#1


54  

This is probably more efficient (faster)

这可能更有效(更快)

def batch(iterable, n=1):
    l = len(iterable)
    for ndx in range(0, l, n):
        yield iterable[ndx:min(ndx + n, l)]

for x in batch(range(0, 10), 3):
    print x

It avoids building new lists.

它避免了构建新列表。

#2


30  

FWIW, the recipes in the itertools module provides this example:

FWIW,itertools模块中的配方提供了这个例子:

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

It works like this:

它的工作原理如下:

>>> list(grouper(3, range(10)))
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, None, None)]

#3


19  

As others have noted, the code you have given does exactly what you want. For another approach using itertools.islice you could see an example of following recipe:

正如其他人所说,您提供的代码完全符合您的要求。对于使用itertools.islice的另一种方法,您可以看到以下配方的示例:

from itertools import islice, chain

def batch(iterable, size):
    sourceiter = iter(iterable)
    while True:
        batchiter = islice(sourceiter, size)
        yield chain([batchiter.next()], batchiter)

#4


4  

Weird, seems to work fine for me in Python 2.x

很奇怪,似乎在Python 2.x中对我很好

>>> def batch(iterable, n = 1):
...    current_batch = []
...    for item in iterable:
...        current_batch.append(item)
...        if len(current_batch) == n:
...            yield current_batch
...            current_batch = []
...    if current_batch:
...        yield current_batch
...
>>> for x in batch(range(0, 10), 3):
...     print x
...
[0, 1, 2]
[3, 4, 5]
[6, 7, 8]
[9]

#1


54  

This is probably more efficient (faster)

这可能更有效(更快)

def batch(iterable, n=1):
    l = len(iterable)
    for ndx in range(0, l, n):
        yield iterable[ndx:min(ndx + n, l)]

for x in batch(range(0, 10), 3):
    print x

It avoids building new lists.

它避免了构建新列表。

#2


30  

FWIW, the recipes in the itertools module provides this example:

FWIW,itertools模块中的配方提供了这个例子:

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

It works like this:

它的工作原理如下:

>>> list(grouper(3, range(10)))
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, None, None)]

#3


19  

As others have noted, the code you have given does exactly what you want. For another approach using itertools.islice you could see an example of following recipe:

正如其他人所说,您提供的代码完全符合您的要求。对于使用itertools.islice的另一种方法,您可以看到以下配方的示例:

from itertools import islice, chain

def batch(iterable, size):
    sourceiter = iter(iterable)
    while True:
        batchiter = islice(sourceiter, size)
        yield chain([batchiter.next()], batchiter)

#4


4  

Weird, seems to work fine for me in Python 2.x

很奇怪,似乎在Python 2.x中对我很好

>>> def batch(iterable, n = 1):
...    current_batch = []
...    for item in iterable:
...        current_batch.append(item)
...        if len(current_batch) == n:
...            yield current_batch
...            current_batch = []
...    if current_batch:
...        yield current_batch
...
>>> for x in batch(range(0, 10), 3):
...     print x
...
[0, 1, 2]
[3, 4, 5]
[6, 7, 8]
[9]