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

Python 迭代列表的n个连续元素(重叠),python,list,iterator,Python,List,Iterator,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

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)?


附言:

应用程序

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

对于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文档中概括
成对的
配方:

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)

这正是的目的,因为
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)]
>>> 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)]
如果您正在寻找可变的组大小,请参阅(我喜欢这种方法),或者更一般地说,您可以实现滑动窗口迭代器并进行切片


另一方面,一个性能可能很差但很有趣的单行窗口(用于控制重叠)不在链接问题上,它是这样的,使用新的
yield from
语法组合生成器

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]
>>> list(pairwise(b))
[(1.0, 1.5), (1.5, 2.0), (2.0, 2.5), (2.5, 3.0)]
>>> 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)]
使用发电机:

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)
结果:

[[1.0, 1.5], [1.5, 2.0], [2.0, 2.5], [2.5, 3.0]]
[[1.0, 1.5, 2.0], [1.5, 2.0, 2.5], [2.0, 2.5, 3.0]]
我认为这个解决方案非常简洁

,正如前面提到的,它没有重叠对

此配方还可在外部库中实现,以及其他有用的功能:

请注意,使用,您可以控制滑动窗口的大小(如果需要,甚至可以通过
步骤
参数控制重叠量)。此工具在您的探索中可能很有用


通过
>pip安装更多itertools

@glibdud安装此库:啊,你说得对。单个tee仍然被包装在一个单元素元组中。第二个示例应该是
b=[tuple(a[i:i+n]),对于x范围内的i(len(a)-n+1)]
,除非我忽略了什么。它似乎缺少一个
+1