Python 列表切片上的迭代

Python 列表切片上的迭代,python,loops,iteration,slice,Python,Loops,Iteration,Slice,我想要一个迭代列表切片的算法。切片大小在函数外部设置,可以不同 在我看来,这有点像: for list_of_x_items in fatherList: foo(list_of_x_items) def callonslices(size, fatherList, foo): for i in xrange(0, len(fatherList), size): foo(fatherList[i:i+size]) 有没有一种方法可以正确定义list\u of_x_item

我想要一个迭代列表切片的算法。切片大小在函数外部设置,可以不同

在我看来,这有点像:

for list_of_x_items in fatherList:
    foo(list_of_x_items)
def callonslices(size, fatherList, foo):
  for i in xrange(0, len(fatherList), size):
    foo(fatherList[i:i+size])
有没有一种方法可以正确定义
list\u of_x_items
,或者使用python 2.5实现这一点的其他方法


edit1:clearification分区和滑动窗口这两个术语听起来都适用于我的任务,但我不是专家。因此,我将更深入地解释这个问题,并补充问题:

父列表是我从文件中获取的多级numpy.array。函数必须找到序列的平均值(用户提供序列的长度),以便使用
mean()
函数进行平均。现在进行问题扩展:

edit2:如何修改您提供的用于存储额外项目的函数,并在将下一个父列表提供给该函数时使用它们

例如,如果列表的长度为10,块的大小为3,则存储列表的第10个成员并将其附加到下一个列表的开头


相关的:

    • 你是说:

      for list_of_x_items in fatherList:
          foo(list_of_x_items)
      
      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]
      
      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)
      
      然后:

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

      你的问题可以更详细一些,但是:

      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)
      
      使用发电机:

      def sliceup(size, fatherList):
        for i in xrange(0, len(fatherList), size):
          yield fatherList[i:i+size]
      
      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
      在序列
      lst
      上实现宽度为
      sliceLen
      的“滑动窗口”,即它产生重叠切片:[1,2,3],[2,3,4],[3,4,5]。。。不过,不确定OP是否有意这样做。

      如果您想使用任何iterable,可以使用以下功能:

      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)
      

      如果要将列表分成多个部分,可以使用以下技巧:

      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
      
      一件物品可以这样消费一次:

      [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
      
      该函数返回元组列表,其中第i个元组包含每个参数序列或iterables中的第i个元素。例如:

      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前面的*用于解压缩参数。你可以找到更多的细节。 所以

      实际上相当于

      zip((1, 20), (2, 30), (3, 40))
      
      但是可以使用数量可变的参数

      现在回到诀窍:

      list_of_slices = zip(*(iter(the_list),) * slice_size)
      
      iter(列表)
      ->将列表转换为迭代器

      (iter(the_list),*N
      ->将生成对_list迭代器的N个引用

      zip(*(iter(the_list),)*N)
      ->将这些迭代器列表输入zip。这反过来会将它们分组为N个大小的元组。但由于所有N项实际上都是对同一迭代器
      iter(列表)
      的引用,因此结果将重复调用原始迭代器上的
      next()

      我希望这就是原因。我建议你选择一个更容易理解的解决方案。我很想提到这个把戏,因为我喜欢它。

      回答问题的最后一部分: 问题更新:如何修改 您为存储提供的功能 这些额外的项目,并在 下一个父亲名单被喂给 功能

      如果需要存储状态,则可以使用对象来存储

      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 = [] 
      
      输出:

      abc
      def
      gh
      

      我不确定,但你似乎想做所谓的移动平均线。numpy为此提供了便利(卷积函数)

      >>>x=numpy.数组(范围(20)) >>>x 数组([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, 17, 18, 19]) >>>n=2#移动平均窗 >>>卷积(numpy.one(n)/n,x)[n-1:-n+1] 阵列([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
      更改为其他方式)

      您可以在此处找到完整的资料:

      对于近一行(在
      itertools
      import之后),按照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)]
      
      如果您愿意,可以使用
      enumerate()
      摆脱
      itertools.count()
      需求,但需要使用一个更丑陋的:

      [ [e[1] for e in grp] for k,grp in itt.groupby(enumerate(myseq), key=lambda x: x[0]//chunksize%2) ]
      
      (在本例中,
      enumerate()
      是多余的,但显然并非所有序列都是这样的整洁范围)


      远没有其他答案那么简洁,但在必要时非常有用,特别是如果已经导入了
      itertools

      扩展了Python 3.7中@Ants Aasma的答案
      StopIteration
      异常的处理(根据)。兼容版本应为:

      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
      

      您似乎在描述一个在原始列表的子集上工作的操作。“切片”可以指单独的连续范围,但您要查找的操作通常称为“分区”。你可能会发现这一点很有帮助:我实际上在思考一个序列上宽度为n的“滑动窗口”,但看看Nadia的答案,这个问题有另一种解释,可能更接近于“划分”。也许OP会澄清这一点。我想你会得到不规则大小的列表。没有确切说明OP想要什么,但这可能更接近:对于xrange中的i(0,len(父列表)-大小,1):更正:对于xrange中的i(len(父列表)-大小+1):“不规则大小”?它们都是len
      大小
      的,但最后一个可能除外,而且不重叠。考虑当LeN为6,大小为7时,代码会发生什么,比如说…减少长度的5片…更好;-)但是对于len 6和size 8,你仍然有同样的问题。我一直在寻找一种可以开箱即用的好东西,因为它看起来像TOT一样