Python的等价物Ruby的each_slice(count)
问题描述:
什么是Ruby的each_slice(count)
等效的python?
我想从每个迭代列表中取2个元素。
像[1,2,3,4,5,6]
我想在第一次迭代处理1,2
然后3,4
然后5,6
。
当然有一个使用指数值的迂回路线。但是有直接的功能还是直接做到这一点?Python的等价物Ruby的each_slice(count)
答
有一个在itertools documentation此一recipe叫石斑鱼:
from itertools import izip_longest
def grouper(n, iterable, fillvalue=None):
"grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return izip_longest(fillvalue=fillvalue, *args)
使用这样的:
>>> l = [1,2,3,4,5,6]
>>> for a,b in grouper(2, l):
>>> print a, b
1 2
3 4
5 6
+0
注意:使用** zip_longest **而不是** izip_longest **作为python 3。 – bwv549 2014-11-25 17:30:50
答
同马克的,但改名为 'each_slice' 和适用于Python 2和3 :
try:
from itertools import izip_longest # python 2
except ImportError:
from itertools import zip_longest as izip_longest # python 3
def each_slice(iterable, n, fillvalue=None):
args = [iter(iterable)] * n
return izip_longest(fillvalue=fillvalue, *args)
答
复制ruby的each_slice行为为一个小trai灵切片:
def each_slice(size, iterable):
""" Chunks the iterable into size elements at a time, each yielded as a list.
Example:
for chunk in each_slice(2, [1,2,3,4,5]):
print(chunk)
# output:
[1, 2]
[3, 4]
[5]
"""
current_slice = []
for item in iterable:
current_slice.append(item)
if len(current_slice) >= size:
yield current_slice
current_slice = []
if current_slice:
yield current_slice
以上意愿垫的答案最后一个列表(即,[5,无]),这可能不是所期望的在某些情况下。
答
对前两项的改进:如果正在切片的迭代不能被n完全整除,则最后一个将被填充到长度为n的无。如果这是造成你输入错误,你可以做一个小的变化:
def each_slice(iterable, n, fillvalue=None):
args = [iter(iterable)] * n
raw = izip_longest(fillvalue=fillvalue, *args)
return [filter(None, x) for x in raw]
请记住,这将删除所有无距离的范围内的,所以只应在情况下使用都不会导致在路上的错误。
mark的回答完全符合您在问题中提供的规范。然而,需要注意的是,他指定的行为偏离了ruby的each_slice:如果最后一个片段比其余片段短,它将填充fillvalue,而在ruby的each_slice中,它仅仅是一个缩短的数组。如果你想要这个缩短的列表/可迭代行为,那么马克的答案将不起作用。 – bwv549 2015-08-24 16:39:51