2014-02-13 19 views
1

的名單如下:算法,以抵消由於數據的列表數據

input = [1,1,1,1,5,5,3,3,3,3,3,3,2,2,2,5,5] 

我想創建一種算法,能夠抵消一定數量的步驟的列表。例如,如果偏移= -1:

def offsetFunc(inputList, offsetList): 
    #make something 
    return output 

其中:

output = [0,0,0,0,1,1,5,5,5,5,5,5,3,3,3,2,2] 

重要提示:列表的元素是浮點數,它們不以任何進展。所以我實際上需要改變他們,我不能使用任何解決方法來獲得結果。

因此,基本上,該算法應替換爲0的第一組值(4「1」,基本上),然後它應:

  1. 檢測值
  2. 的下一個範圍的lenght
  3. 創建並行輸出向量,其值延遲一組

我大致描述了上述算法的方式是如何做。然而,我是Python的新手(甚至是一般編程的初學者),我已經逐漸認識到Python有很多內置函數可以使算法變得更加輕量和迭代。有沒有人有任何建議來更好地開發腳本來完成這種工作?這是我迄今寫的代碼(假設靜態偏移量爲-1):

input = [1,1,1,1,5,5,3,3,3,3,3,3,2,2,2,5,5] 
output = [] 
PrevVal = 0 
NextVal = input[0] 
i = 0 
while input[i] == NextVal: 
    output.append(PrevVal) 
    i += 1 

while i < len(input):  
    PrevVal = NextVal 
    NextVal = input[i] 
    while input[i] == NextVal: 
     output.append(PrevVal) 
     i += 1 
     if i >= len(input): 
      break 

print output 

在此先感謝您的幫助!

更好的描述 我的列表將始終由值的「集合」組成。它們通常是浮點數,並且它們取的值,如低於該短例如:

Sample = [1.236,1.236,1.236,1.236,1.863,1.863,1.863,1.863,1.863,1.863] 

在這個例子中,第一組(具有值「1.236」)是長4,而第二個是長6 。當偏移量= -1時,我希望得到的結果是:

  1. 前4個元素中的值「0.000」
  2. 第二個6個元素中的值「1.236」。

因此,基本上,這種「偏移」功能與相同的「結構」(長度範圍),但與由延遲值創建列表「偏移」倍

我希望現在很清楚,不幸的是問題本身對我來說仍然有點愚蠢(加上我甚至不說英語:) :) 請不要猶豫,要求任何額外的信息來完成問題和使其更清晰。

+0

你可以添加一個例子offset = -2嗎? – amit

+0

當然。它會變成:'output = [0,0,0,0,0,0,1,1,1,1,1,1,5,5,5,3,3]'。基本上,假設第一個「(偏移量)相同的值集合」(例如,如果offset = -2,前兩組相同的值)將變爲0,而其餘的將具有相同的長度,但是「 (2)之前的值集合。 –

+0

偏移量總是負值?或者「積極」的抵消意味着「向左移動」而不是向右移動? – amit

回答

6

如何:

def generateOutput(input, value=0, offset=-1): 
    values = [] 
    for i in range(len(input)): 
    if i < 1 or input[i] == input[i-1]: 
     yield value 
    else: # value change in input detected 
     values.append(input[i-1]) 
     if len(values) >= -offset: 
     value = values.pop(0) 
     yield value 

input = [1,1,1,1,5,5,3,3,3,3,3,3,2,2,2,5,5] 
print list(generateOutput(input)) 

它會打印:

[0, 0, 0, 0, 1, 1, 5, 5, 5, 5, 5, 5, 3, 3, 3, 2, 2] 

而你只是想迭代的情況下,你甚至都不需要建立名單。那麼只需使用for i in generateOutput(input): …即可。

對於其他偏移,使用:

print list(generateOutput(input, 0, -2)) 

打印:

[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 5, 5, 5, 3, 3] 
+0

我很抱歉,但我意識到我用過的例子是誤解。我剛剛編輯了這個問題,我需要的是實際移回元素(而不僅僅是它們的值):) –

+1

它適合(原始)例子,但它從來沒有適合問題的實際描述。刪除/更新答案是明智的。 – amit

+0

我看到了,並更新了我的答案。 – Alfe

1
def x(list, offset): 
    return [el + offset for el in list] 
+0

我很抱歉,但我意識到我用過的例子是誤解。我剛剛編輯它,我需要的是實際移動元素而不僅僅是它們的值:) –

2

使用deque作爲隊列,以及使用的maxlen定義移位長度。只保持獨特的價值。在結束時推送新值,在排隊長度達到時,在隊列開始時推出舊值。

from collections import deque 

def shift(it, shift=1): 
    q = deque(maxlen=shift+1) 
    q.append(0) 
    for i in it: 
     if q[-1] != i: 
      q.append(i) 
     yield q[0] 


Sample = [1.236,1.236,1.236,1.236,1.863,1.863,1.863,1.863,1.863,1.863] 

print list(shift(Sample)) 
#[0, 0, 0, 0, 1.236, 1.236, 1.236, 1.236, 1.236, 1.236] 
+0

是的,我喜歡使用固定大小的'deque'。 – Alfe

2

我嘗試:

#Input 
input = [1,1,1,1,5,5,3,3,3,3,3,3,2,2,2,5,5] 
shift = -1 

#Build service structures: for each 'set of data' store its length and its value 
set_lengths = [] 
set_values = [] 

prev_value = None 
set_length = 0 
for value in input: 
    if prev_value is not None and value != prev_value: 
     set_lengths.append(set_length) 
     set_values.append(prev_value) 
     set_length = 0 
    set_length += 1 
    prev_value = value 
else: 
    set_lengths.append(set_length) 
    set_values.append(prev_value) 

#Output the result, shifting the values 
output = [] 
for i, l in enumerate(set_lengths): 
    j = i + shift 
    if j < 0: 
     output += [0] * l 
    else: 
     output += [set_values[j]] * l 

print input 
print output 

給出:

[1, 1, 1, 1, 5, 5, 3, 3, 3, 3, 3, 3, 2, 2, 2, 5, 5] 
[0, 0, 0, 0, 1, 1, 5, 5, 5, 5, 5, 5, 3, 3, 3, 2, 2] 
1

完全不同的方法比我的第一個答案是這樣的:

import itertools 

首先分析輸入:

values, amounts = zip(*((n, len(list(g))) for n, g in itertools.groupby(input))) 

我們現在有(1, 5, 3, 2, 5)(4, 2, 6, 3, 2)。現在應用偏移:

values = (0,) * (-offset) + values # nevermind that it is longer now. 

而再次合成它:

output = sum([ [v] * a for v, a in zip(values, amounts) ], []) 

這是方式更優雅,方式更難理解和可能的方式比我其他的答案更貴,但我不想把它藏起來。