2017-12-12 6 views
7

に等しい場合、値を保持し、私は(連続mesuresを表す)信号のリストを持っている:PythonリストのみN先行

signals = [0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0] 

Iは、過去n mesuresに等しい場合に信号が有効考えます。

例:検証のために2つのメッシュしか考慮しない場合、最初の信号は0から1に変化しますが、それでも0と見なされますが、次のメッシュと見なされます。再度1であれば、それはまだ有効です。 0のメッシュを0に戻すなど、ここで信号は0と1ですが、私のアプリケーションでは他の整数にすることができます。

所望の出力:私はそれを行うのpythonesqueワンライナーの方法の探していたが、所望の出力を見つけることができないよう

# For n = 2: 
valid_s = [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0] 

# For n = 3: 
valid_s = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0] 

# For n = 4: 
valid_s = [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0] 

S = signals 

# For n = 2 
[S[i] if S[i] == S[i-1] else S[i-2] for i, _ in enumerate(S)] 
# gives [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0] 

# For n = 3 
[S[i] if S[i] == S[i-1] == S[i-2] else S[i-3] for i, _ in enumerate(S)] 
# gives [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0] 

編集:私は線に沿って何かをしようとしたことがすでにインポートだとして、それが容易になります場合、私はnumpyに開いています。

+0

n = 2の出力は正しいですか?あなたは、測定値または既に "修正された"以前の値にのみ出力を基づいていますか? – voiDnyx

+0

はい、n = 2の場合、1または0に切り替えることを検討するには2つの連続する1または0が必要です。2つ連続していない場合、前に既に検証された値を保持します。したがって、n = 2に対する所望の出力。 – Fredovsky

答えて

5

これを1ライナー/リストの理解にする良い方法はないと思います。リストのスライスにallを使用して値が以前の値のnと同じかどうかを確認することができましたが、そうでない場合に最後の有効な値を決定する良い方法はありません。

代わりに、あなたはループのために良い、古い "多くのラインを" 使用することができます

signals = [0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0] 
n = 3 

last_valid = 0 
current = None 
repeated = 0 
res = [] 
for s in signals: 
    if s == current: 
     repeated += 1 
    else: 
     repeated = 1 
     current = s 
    if repeated >= n: 
     last_valid = s 
    res.append(last_valid) 

その後、res[0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0]


itertools.groupbyを使用して、代わりに、少し短いです。結果は同じです:

last_valid = 0 
res = [] 
for k, g in itertools.groupby(signals): 
    m = len(list(g)) 
    if m >= n: 
     res.extend([last_valid] * (n-1) + [k] * (m-n+1)) 
     last_valid = k 
    else: 
     res.extend([last_valid] * m) 
+2

補遺:そして、いつものように、1行の解決策が必要な場合は、それを関数にしてください。 ;-) –

+0

ビットが短く多分もっとシンプルです:https://ideone.com/vtjVUW –

+1

ああ、*もっと*短く/シンプル:https://ideone.com/cgEnpu –

2
signal = [0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0] 

def each(signal, n): 
    p = 0 
    ring = [ signal[0] ] * (n-1) 
    v = None 
    for x in signal: 
    if v is None or all(q == x for q in ring): 
     v = x 
    yield v 
    ring[p] = x 
    p = (p+1) % (n-1) 

list(each(signal, 2)) 
[0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0] 

しかし、私はこれを再検討し、純粋な反復(以下Python的)アプローチは、おそらく、より効率的であると思います。私の新しいアプローチを完了した後、私は今、彼の答えで既に実装されている@tobias_kと同じ考えであると思っています:

+0

なぜ 'リング'ですか?リストの一部だけではないのはなぜですか? –

+0

スライスの作成はリングバッファを使用するよりもコストがかかる可能性が高いためです。私が頼りにしたくない実装に依存します。 – Alfe

+0

有効な点ですが、全体の複雑さは依然として 'O(len(lst)* n)' –

関連する問題