在这里发布这样的问题不是像这样的问题添加到Python的方式。你应该尝试一个Python邮件列表。
我用你请求的语义为你实现了chunks()
。最后一块的处理恰到好处是有点棘手,但否则这很容易。如果它被添加到itertools
它将被写入C,所以它会更快。
在Python 2.6,Python 2.7和Python 3.2中进行测试和工作。
import itertools as it
import sys
# use lazy xrange on 2.x; on 3.x plain "range" is always lazy
if sys.version_info[0] < 3:
_range = xrange
else:
_range = range
def chunks(iterable, n):
"""
Yield up lists of n elements, taken from iterable.
If length of iterable is not evenly divisible by n, the last list will be short.
"""
if n < 1:
raise ValueError("n must be >= 1")
itr = iter(iterable)
try:
while True:
lst = []
for _ in _range(n):
lst.append(next(itr))
if not lst:
break
yield lst
except StopIteration:
# Only yield up a partial chunk if it is not zero length.
if lst:
yield lst
print(list(chunks([1, 2, 3, 4, 5, 6], 3))) # prints: [[1, 2, 3], [4, 5, 6]]
print(list(chunks([1, 2, 3, 4, 5], 3))) # prints: [[1, 2, 3], [4, 5]]
print(list(chunks([], 3))) # prints: []
print(list(chunks([1, 2], 0))) # raises ValueError exception
编辑:
上述解决方案的效率低下是有点缠着我。我很确定必须使用itertools.islice()
更简单的解决方案,所以我想通了。我更喜欢这个。
def chunks(iterable, n):
"""
Yield up lists of n elements, taken from iterable.
If length of iterable is not evenly divisible by n, the last list will be short.
"""
if n < 1:
raise ValueError("n must be >= 1")
itr = iter(iterable)
while True:
lst = list(it.islice(itr, n))
if not lst:
break
yield lst
因为它的简单和明显不够使用列表理解在一行来实现? – wim 2013-05-01 05:28:59
@wim这听起来像是我的另一个原因:) – razpeitia 2013-05-01 05:42:54
滑动窗口迭代器将是我将添加到标准库的另一个。 – 2013-05-01 06:10:41