2017-04-19 75 views
0

我試圖做一個生成器,它可以返回列表中只有一個索引「移動」的多個連續項目。類似於DSP中的移動平均濾波器。舉例來說,如果我有列表:返回組項目的Python生成器

l = [1,2,3,4,5,6,7,8,9] 

我希望這樣的輸出:

[(1,2,3),(2,3,4),(3,4,5),(4,5,6),(5,6,7),(6,7,8),(7,8,9)] 

我做的代碼,但它不帶過濾器和發電機等,恐怕也將打破由於工作記憶,如果我需要提供一個大的單詞列表。

功能gen

def gen(enumobj, n): 
    for idx,val in enumerate(enumobj): 
     try: 
      yield tuple(enumobj[i] for i in range(idx, idx + n)) 
     except: 
      break 

和示例代碼:

words = ['aaa','bb','c','dddddd','eeee','ff','g','h','iiiii','jjj','kk','lll','m','m','ooo'] 
w = filter(lambda x: len(x) > 1, words) 

# It's working with list 
print('\nList:') 
g = gen(words, 4) 
for i in g: print(i) 

# It's not working with filetrs/generators etc. 
print('\nFilter:') 
g = gen(w, 4) 
for i in g: print(i) 

名單不會產生任何東西。代碼應該中斷,因爲無法索引過濾器對象。當然,其中一個答案是強制列表:list(w)。但是,我正在尋找更好的函數代碼。我怎樣才能改變它,使函數可以接受過濾器等等。我擔心內存中列表中的大量數據。

謝謝

回答

1

使用迭代器,您需要跟蹤已讀取的值。一個n大小的清單是訣竅。將下一個值附加到列表中,並在每個收益率後放棄頂部項目。

import itertools 

def gen(enumobj, n): 
    # we need an iterator for the `next` call below. this creates 
    # an iterator from an iterable such as a list, but leaves 
    # iterators alone. 
    enumobj = iter(enumobj) 
    # cache the first n objects (fewer if iterator is exhausted) 
    cache = list(itertools.islice(enumobj, n)) 
    # while we still have something in the cache... 
    while cache: 
     yield cache 
     # drop stale item 
     cache.pop(0) 
     # try to get one new item, stopping when iterator is done 
     try: 
      cache.append(next(enumobj)) 
     except StopIteration: 
      # pass to emit progressively smaller units 
      #pass 
      # break to stop when fewer than `n` items remain 
      break 

words = ['aaa','bb','c','dddddd','eeee','ff','g','h','iiiii','jjj','kk','lll','m','m','ooo'] 
w = filter(lambda x: len(x) > 1, words) 

# It's working with list 
print('\nList:') 
g = gen(words, 4) 
for i in g: print(i) 

# now it works with iterators 
print('\nFilter:') 
g = gen(w, 4) 
for i in g: print(i) 
+0

嗨。我需要詢問一些事情。我是否正確地說前兩行是初始化發生器,並且只在發生器開始工作時才運行?它看起來像迭代需要它們第一次切片對象。在''data':'和'data'爲什麼會檢查什麼樣的條件?對我來說,該函數通過'yield data'返回暫停的值,然後代碼返回到下一行繼續。那是對的嗎?抱歉,我是製作發電機的新手。謝謝 – Celdor

+0

我已將'pass'改爲'break'。否則,函數會返回長度爲n-1,n-2,...,1的多餘項目。 – Celdor

+0

如果迭代器的起始項少於「n」項,這也可能是個問題。你可以在'islice'後面加一個檢查並立即返回。 – tdelaney