【发布时间】:2010-12-27 06:36:15
【问题描述】:
我正在尝试用 Python 编写 Haskell 函数“splitEvery”。这是它的定义:
splitEvery :: Int -> [e] -> [[e]]
@'splitEvery' n@ splits a list into length-n pieces. The last
piece will be shorter if @n@ does not evenly divide the length of
the list.
它的基本版本可以正常工作,但我想要一个可以与生成器表达式、列表和迭代器一起使用的版本。 而且,如果有一个生成器作为输入,它应该返回一个生成器作为输出!
测试
# should not enter infinite loop with generators or lists
splitEvery(itertools.count(), 10)
splitEvery(range(1000), 10)
# last piece must be shorter if n does not evenly divide
assert splitEvery(5, range(9)) == [[0, 1, 2, 3, 4], [5, 6, 7, 8]]
# should give same correct results with generators
tmp = itertools.islice(itertools.count(), 10)
assert list(splitEvery(5, tmp)) == [[0, 1, 2, 3, 4], [5, 6, 7, 8]]
当前实施
这是我目前拥有的代码,但它不适用于简单的列表。
def splitEvery_1(n, iterable):
res = list(itertools.islice(iterable, n))
while len(res) != 0:
yield res
res = list(itertools.islice(iterable, n))
这个不适用于生成器表达式(感谢 jellybean 修复它):
def splitEvery_2(n, iterable):
return [iterable[i:i+n] for i in range(0, len(iterable), n)]
必须有一段简单的代码来进行拆分。我知道我可以拥有不同的功能,但它似乎应该很容易做到。我可能陷入了一个不重要的问题,但这真的让我很烦恼。
它类似于http://docs.python.org/library/itertools.html#itertools.groupby 的 grouper,但我不希望它填充额外的值。
def grouper(n, iterable, fillvalue=None):
"grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return izip_longest(fillvalue=fillvalue, *args)
它确实提到了一种截断最后一个值的方法。这也不是我想要的。
保证迭代的从左到右的评估顺序。这使得使用 izip(*[iter(s)]*n) 将数据系列聚类为 n 长度组成为可能。
list(izip(*[iter(range(9))]*5)) == [[0, 1, 2, 3, 4]]
# should be [[0, 1, 2, 3, 4], [5, 6, 7, 8]]
【问题讨论】:
-
相关的“以块为单位迭代列表的最“pythonic”方式是什么?” stackoverflow.com/questions/434287/…