我偶然看到两种不同的方式将一个iterable拆分为“块”(超过一个项)。
from itertools import izip_longest
def grouper(iterable, n, fillvalue=None):
args = [iter(iterable)] * n
return izip_longest(*args, fillvalue=fillvalue)def chunker(seq, size):
return (seq[pos:pos + size] for pos in xrange(0, len(seq), size))迭代工具实现为您购买“额外”的东西吗?
在“额外”的地方,也许更快、更灵活、更安全。
我之所以这样问,是因为这里显示的迭代工具实现绝对不是更易读/更直观的IMO。
发布于 2017-09-22 11:25:10
grouper可以与任何可迭代一起使用--包括生成器和无限迭代器。chunker只能与长度可以预先确定的序列迭代一起使用。
from itertools import izip_longest
def grouper(iterable, n, fillvalue=None):
args = [iter(iterable)] * n
return izip_longest(*args, fillvalue=fillvalue)
def chunker(seq, size):
return (seq[pos:pos + size] for pos in xrange(0, len(seq), size))
x = (i**2 for i in range(5))
print(list(grouper(x, 3)))
# [(0, 1, 4), (9, 16, None)]
print(list(chunker(x, 3)))
# TypeError: object of type 'generator' has no len()发布于 2017-09-23 15:05:09
这两个函数不是等价的。有几个不同之处:
grouper适用于任何可迭代的(包括迭代器和生成器),而chunker则需要支持索引([...])的序列。
it = lambda:(i for i in range(6)) #在称为>>>列表时创建一个生成器(石斑鱼(it(),3)) (0,1,2),(3,4,5) >>>列表(chunker(it(),3) TypeError:类型为‘生成器’的对象没有len()
请注意,另一个答案已经提到了这一点!chunker的最后一个元素将小于块大小。OTOH grouper将填充一些填充值。此外,chunker将返回与原始类型相同的类型,而grouper将返回tuples:清单(石斑鱼(1,2,3,4,5,3)) (1,2,3,5),(4,5,无) >>>列表(块状(1,2,3,4,5,3) ) [1,2,3,4,4,5]grouper使用高性能的内置iter和zip_longest。这些会很快的。以牺牲可读性为代价。然而,这可以使它比chunker快得多:
L=列表(范围(10000) %timeit list(石斑鱼(1,10)) # 320 s±6.39s/圈(平均±std )。dev.在7次运行中,每个循环1000次) %timeit列表(chunker(l,10)) #1.22ms±19s/循环(平均±std )。dev.7次运行中,每一次有1000次循环)因此,grouper是一种比chunker更快、更通用的方法。但是,根据情况的不同,使用chunker可能更有用,例如,如果您不喜欢“填充”-part或希望保留“块”的类型。
https://stackoverflow.com/questions/46363576
复制相似问题