itertools python模块为迭代器实现了一些基本构建块。正如他们所说,“它们构成了迭代器代数”。我期待,但我找不到使用该模块进行以下迭代的简洁方法。给出有序实数列表,例如
a = [1.0,1.5,2.0,2.5,3.0]
...按一些n
值返回一个新列表(或只是迭代)分组,比如2
b = [(1.0,1.5),(1.5,2.0),(2.0,2.5),(2.5,3.0)]
我发现这样做的方式如下。首先将列表分为两部分,使用均衡和赔率索引:
even, odds = a[::2], a[1::2]
然后构建新列表:
b = [(even, odd) for even, odd in zip(evens, odds)]
b = sorted(b + [(odd, even) for even, odd in zip(evens[1:], odds)])
本质上,它类似于移动平均值。
有没有简洁的方法(有或没有itertools)?
PS:
应用
想象一下a
列表作为实验期间发生的一些事件的时间戳集:
timestamp event
47.8 1a
60.5 1b
67.4 2a
74.5 2b
78.5 1a
82.2 1b
89.5 2a
95.3 2b
101.7 1a
110.2 1b
121.9 2a
127.1 2b
...
此代码用于根据不同的时间窗口对这些事件进行分段。现在我对2
个连续事件之间的数据感兴趣; 'n> 2'仅用于探索目的。
答案 0 :(得分:8)
这正是pairwise
itertools recipe的目的,n=2
就是from itertools import tee
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return zip(a, b)
。
>>> b = [1.0,1.5,2.0,2.5,3.0]
>>> list(pairwise(b))
[(1.0, 1.5), (1.5, 2.0), (2.0, 2.5), (2.5, 3.0)]
<强>演示强>:
yield from
如果您正在寻找变量组大小,请参阅user2357112's answer(我喜欢这种方法),或者更一般地说,您可以实现滑动窗口迭代器并获取切片of which there are many approaches。
顺便说一句,一个可能性能很差但很有趣的单行窗口,你可以切片(来控制重叠),而不是链接的问题就是这样,使用新的{{ 1}}语法来组合生成器。
from itertools import tee, islice
def roll_window(it, sz):
yield from zip(*[islice(it, g, None) for g, it in enumerate(tee(it, sz))])
<强>演示强>:
>>> b = [1.0,1.5,2.0,2.5,3.0, 3.5, 4.0, 4.5]
>>> list(islice(window(b, 3), None, None, 2))
[(1.0, 1.5, 2.0), (2.0, 2.5, 3.0), (3.0, 3.5, 4.0)]
答案 1 :(得分:6)
对于2,你可以做到
b = zip(a, a[1:]) # or list(zip(...)) on Python 3 if you really want a list
对于固定n,技术类似:
# n = 4
b = zip(a, a[1:], a[2:], a[3:])
对于变量n,您可以压缩可变数量的切片,或者(特别是如果窗口大小接近a
的大小),您可以使用切片直接获取窗口:
b = zip(*[a[i:] for i in xrange(n)])
# or
b = [tuple(a[i:i+n]) for i in xrange(len(a)-n+1)]
如果a
不是列表,您可以从itertools文档中推广pairwise
配方:
import copy
import itertools
def nwise(iterable, n):
# Make n tees at successive positions along the iterable.
tees = list(itertools.tee(iterable, 1))
for _ in xrange(n-1):
tees.append(copy.copy(tees[-1]))
next(tees[-1])
return zip(*tees)
答案 2 :(得分:1)
使用发电机:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="copy"></div>
结果:
def groupListByN(lst, n):
for i in range(len(a)-n+1):
yield lst[i:i+n]
a = [1.0,1.5,2.0,2.5,3.0]
myDoubleList = [group for group in groupListByN(a, 2)]
myTripleList = [group for group in groupListByN(a, 3)]
print(myDoubleList)
print(myTripleList)
我认为这个解决方案非常简洁
答案 3 :(得分:0)
如前所述,pairwise
recipe会重叠重叠。
此食谱还可以在外部库more_itertools
中实现,以及其他有用的windowing tools:
import more_itertools as mit
a = [1.0, 1.5, 2.0, 2.5, 3.0]
list(mit.pairwise(a))
# [(1.0, 1.5), (1.5, 2.0), (2.0, 2.5), (2.5, 3.0)]
list(mit.windowed(a, n=2))
# [(1.0, 1.5), (1.5, 2.0), (2.0, 2.5), (2.5, 3.0)]
list(mit.stagger(a, offsets=(0, 1)))
# [(1.0, 1.5), (1.5, 2.0), (2.0, 2.5), (2.5, 3.0)]
注意,使用more_itertools.windowed
,您可以控制n
,滑动窗口的大小(甚至可以通过step
参数控制重叠窗口的大小)。此工具可能对您的探索有用。
通过> pip install more_itertools
安装此库。