我想要一个算法的迭代表片。切片大小组之外的功能,并可能有所不同。

在我心中就是这样的:

for list_of_x_items in fatherList:
    foo(list_of_x_items)

有没有办法适当地定义 list_of_x_items 或者一些其他的方式这样做使用python2.5?


edit1:澄清 这两个"分区"和"滑动窗口"条款的声音适用于我的任务,但我没有专家。所以我会解释的问题,一位更深入和加入的问题:

该fatherList是一个多层次的顽固.阵列,我来自一个文件。功能已经找到平均水平的系列(用户提供的长度系列的)对于平均的,我用的 mean() 功能。现在问题扩大:

edit2: 如何修改的功能,你有提供存储的额外项目,并利用他们在下一fatherList被送到功能?

例如,如果名单是长10和大小的区块是3,然后10日的成员名单存储和所附的开始下一个列表。


相关:

有帮助吗?

解决方案

答案的最后部分问题:

问题的更新:如何修改 功能的提供商店 额外的项目,并使用他们的时候的 下一fatherList被送来的 功能?

如果你需要储存国家然后可以使用的对象。

class Chunker(object):
    """Split `iterable` on evenly sized chunks.

    Leftovers are remembered and yielded at the next call.
    """
    def __init__(self, chunksize):
        assert chunksize > 0
        self.chunksize = chunksize        
        self.chunk = []

    def __call__(self, iterable):
        """Yield items from `iterable` `self.chunksize` at the time."""
        assert len(self.chunk) < self.chunksize
        for item in iterable:
            self.chunk.append(item)
            if len(self.chunk) == self.chunksize:
                # yield collected full chunk
                yield self.chunk
                self.chunk = [] 

例如:

chunker = Chunker(3)
for s in "abcd", "efgh":
    for chunk in chunker(s):
        print ''.join(chunk)

if chunker.chunk: # is there anything left?
    print ''.join(chunker.chunk)

输出:

abc
def
gh

其他提示

如果你想要来划分列入切片你可以使用这种技巧:

list_of_slices = zip(*(iter(the_list),) * slice_size)

例如

>>> zip(*(iter(range(10)),) * 3)
[(0, 1, 2), (3, 4, 5), (6, 7, 8)]

如果项目的数量是不可分割的切片大小和你想垫的名单没有你可以这样做:

>>> map(None, *(iter(range(10)),) * 3)
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, None, None)]

这是一个肮脏的小把戏


好吧,我会解释它是如何工作的。这将是棘手的解释,但我会尽我所能。

第一一个小小的背景:

在Python你可以乘一个列表中的一些这样的:

[1, 2, 3] * 3 -> [1, 2, 3, 1, 2, 3, 1, 2, 3]
([1, 2, 3],) * 3 -> ([1, 2, 3], [1, 2, 3], [1, 2, 3])

和一个 迭代 对象可以使用一次这样的:

>>> l=iter([1, 2, 3])
>>> l.next()
1
>>> l.next()
2
>>> l.next()
3

拉链 功能返回的一个单元组,在那里我第元组包含我个元素从每个参数序列或可迭代对象.例如:

zip([1, 2, 3], [20, 30, 40]) -> [(1, 20), (2, 30), (3, 40)]
zip(*[(1, 20), (2, 30), (3, 40)]) -> [[1, 2, 3], [20, 30, 40]]

*的拉链用于解论点。你可以找到更多细节 在这里,.所以

zip(*[(1, 20), (2, 30), (3, 40)])

实际上相当于

zip((1, 20), (2, 30), (3, 40))

但适用一个变量的参数数目

现在回到窍门:

list_of_slices = zip(*(iter(the_list),) * slice_size)

iter(the_list) ->的转换列入一个迭代

(iter(the_list),) * N ->将产生一个N的参考the_list迭代器。

zip(*(iter(the_list),) * N) ->将料的那些清单的迭代进入拉链。这反过来将他们组成N大元组。但是,由于所有项目都是在事实上的引用同一个迭代 iter(the_list) 结果将重复调用 next() 在原来的迭代

我希望解释它。我建议你去与一个容易理解的解决方案。我只是想提到这个把戏,因为我喜欢它。

如果你想要能够消耗的任何可迭代可以利用这些功能:

from itertools import chain, islice

def ichunked(seq, chunksize):
    """Yields items from an iterator in iterable chunks."""
    it = iter(seq)
    while True:
        yield chain([it.next()], islice(it, chunksize-1))

def chunked(seq, chunksize):
    """Yields items from an iterator in list chunks."""
    for chunk in ichunked(seq, chunksize):
        yield list(chunk)

你的意思是这样的:

def callonslices(size, fatherList, foo):
  for i in xrange(0, len(fatherList), size):
    foo(fatherList[i:i+size])

如果这是大致的功能你想要的你也许,如果你的愿望,穿着它一点在一个发生器:

def sliceup(size, fatherList):
  for i in xrange(0, len(fatherList), size):
    yield fatherList[i:i+size]

然后:

def callonslices(size, fatherList, foo):
  for sli in sliceup(size, fatherList):
    foo(sli)

使用发电机:

big_list = [1,2,3,4,5,6,7,8,9]
slice_length = 3
def sliceIterator(lst, sliceLen):
    for i in range(len(lst) - sliceLen + 1):
        yield lst[i:i + sliceLen]

for slice in sliceIterator(big_list, slice_length):
    foo(slice)

sliceIterator 实现"滑动窗口"的宽度 sliceLen 在将 lst, 即它产生重叠片:[1,2,3], [2,3,4], [3,4,5], ...不知道,如果是运的意图,虽然。

我不确定,但它似乎你想要做什么被称为移动平均值。顽固提供设施用于本(该卷积功能)。

>>> x = numpy.array(range(20))
>>> x
    array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
       17, 18, 19])    
>>> n = 2 # moving average window
>>> numpy.convolve(numpy.ones(n)/n, x)[n-1:-n+1]
array([  0.5,   1.5,   2.5,   3.5,   4.5,   5.5,   6.5,   7.5,   8.5,
         9.5,  10.5,  11.5,  12.5,  13.5,  14.5,  15.5,  16.5,  17.5,  18.5])

这种做法的好处是,它可容纳不同的加权计划很好(只是改变 numpy.ones(n) / n 到别的东西).

你可以找到一个完整的材料:http://www.scipy.org/Cookbook/SignalSmooth

你的问题可以使用一些更详细的说明,但是,如何约:

def iterate_over_slices(the_list, slice_size):
    for start in range(0, len(the_list)-slice_size):
        slice = the_list[start:start+slice_size]
        foo(slice)

对于一个近一个衬垫(后 itertools 进口)的静脉Nadia的答案,处理非块可分割的尺寸没有填充:

>>> import itertools as itt
>>> chunksize = 5
>>> myseq = range(18)
>>> cnt = itt.count()
>>> print [ tuple(grp) for k,grp in itt.groupby(myseq, key=lambda x: cnt.next()//chunksize%2)]
[(0, 1, 2, 3, 4), (5, 6, 7, 8, 9), (10, 11, 12, 13, 14), (15, 16, 17)]

如果你想,你可以摆脱的 itertools.count() 要求使用 enumerate(), ,而不是丑陋:

[ [e[1] for e in grp] for k,grp in itt.groupby(enumerate(myseq), key=lambda x: x[0]//chunksize%2) ]

(在这个例子的 enumerate() 将是多余的,但并不是所有的序列整齐的范围如此,很明显)

远不及整洁如一些其他的答案,但是有用的,在一个紧要关头,尤其是如果已经导入 itertools.

扩大在答案@蚂蚁Aasma:在Python3.7处理的 StopIteration 异常 改变了 (根据 PEP-479).一个兼容的版本将包括:

from itertools import chain, islice

def ichunked(seq, chunksize):
    it = iter(seq)
    while True:
        try:
            yield chain([next(it)], islice(it, chunksize - 1))
        except StopIteration:
            return
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top