2016-07-01 59 views
1

itertools python模塊爲迭代器實現了一些基本構建塊。正如他們所說,「他們形成了一個迭代代數」。我期待着,但是我找不到使用模塊進行下面迭代的簡潔方法。鑑於有序實數列表,例如遍歷n個連續列表元素(重疊)

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

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 

... 

此代碼是:


PS:

應用

想象a列表作爲設定一些事件的時間戳的實驗過程中發生用於根據不同的時間窗口來分割這些事件。現在我對2連續事件之間的數據感興趣; 'n> 2'將僅用於探索目的。

回答

3

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

如果a不是一個列表,你可以從迭代工具文檔概括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) 
+0

@glibdud:啊,你說得對。單T恤仍然包裹在一個元素元組中。 – user2357112

4

這也恰恰是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)] 

如果您正在尋找變量組大小,見user2357112's answer(我喜歡的方式),或者更一般可以實現滑動窗口迭代器,並採取切片of which there are many approaches


順便說一句,一個表演可能不佳,但有趣的一個行窗口中,你可以切片(控制重疊),是不是對鏈接的問題是這樣,使用新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, 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

使用發電機:

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

我認爲這個解決方案是相當簡潔