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

2022-01-10 00:00:00 python list iterator

问题描述

itertools python 模块为迭代器实现了一些基本构建块.正如他们所说,它们形成了一个迭代器代数".我期待,但我找不到使用该模块进行以下迭代的简洁方法.给定一个有序实数列表,例如

The itertools python module implements some basic building blocks for iterators. As they say, "they form an iterator algebra". I was expecting, but I could not find a succinctly way of doing the following iteration using the module. Given a list of ordered real numbers, for example

a = [1.0,1.5,2.0,2.5,3.0]

...返回一个新列表(或只是迭代)按一些 n 值分组,比如 2

... return a new list (or just iterate) grouping by some n value, say 2

b = [(1.0,1.5),(1.5,2.0),(2.0,2.5),(2.5,3.0)]

我发现这样做的方法如下.首先将列表一分为二,带有偶数和赔率索引:

The way I found of doing this was as follows. First split the list in two, with evens and odds indexes:

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

本质上,它类似于移动均值.

In essence, it is similar to a moving mean.

是否有简洁的方法(使用或不使用 itertools)?

PS:

应用程序

a 列表想象为实验期间发生的某些事件的时间戳集:

Imagine the a list as the set of timestamps of some events occurred during an experiment:

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

This code is being used to segment those events in accord with different temporal windows. Right now I am interested in the data between 2 successive events; 'n > 2' would be used only for exploratory purposes.


解决方案

对于2,你可以这样做

b = zip(a, a[1:])  # or list(zip(...)) on Python 3 if you really want a list

对于固定的 n,技术类似:

For fixed n, the technique is similar:

# n = 4
b = zip(a, a[1:], a[2:], a[3:])

对于变量 n,您可以压缩可变数量的切片,或者(尤其是当窗口大小接近 a 的大小时)您可以使用切片直接获取窗口:

For variable n, you could zip a variable number of slices, or (especially if the window size is close to the size of a) you could use slicing to take windows directly:

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 配方:

If a is not a list, you could generalize the pairwise recipe from the itertools docs:

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)

相关文章