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一样