2010-09-30 106 views
5

什么是Ruby的each_slice(count)等效的python?
我想从每个迭代列表中取2个元素。
[1,2,3,4,5,6]我想在第一次迭代处理1,2然后3,4然后5,6
当然有一个使用指数值的迂回路线。但是有直接的功能还是直接做到这一点?Python的等价物Ruby的each_slice(count)

+0

mark的回答完全符合您在问题中提供的规范。然而,需要注意的是,他指定的行为偏离了ruby的each_slice:如果最后一个片段比其余片段短,它将填充fillvalue,而在ruby的each_slice中,它仅仅是一个缩短的数组。如果你想要这个缩短的列表/可迭代行为,那么马克的答案将不起作用。 – bwv549 2015-08-24 16:39:51

回答

9

有一个在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

2

同马克的,但改名为 '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) 
0

复制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,无]),这可能不是所期望的在某些情况下。

0

对前两项的改进:如果正在切片的迭代不能被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] 

请记住,这将删除所有无距离的范围内的,所以只应在情况下使用都不会导致在路上的错误。