迭代n个连续的列表元素(重叠)

时间:2016-07-01 18:00:20

标签: python list iterator

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'仅用于探索目的。

4 个答案:

答案 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安装此库。