2011-08-04 2 views
5

現在の反復要素がリストにない場合にのみ、要素をリストに追加する必要があります。リストの理解はここで適切ですか?

>>> l = [1, 2] 
>>> [l.append(i) for i in (2, 3, 4) if i not in l] 
[None, None] 
>>> l 
[1, 2, 3, 4] 

>>> l = [1, 2] 
>>> for x in (2, 3, 4): 
...  if x not in l: 
...    l.append(x) 
... 
>>> l 
[1, 2, 3, 4] 

リストの内包はちょうど返されるリストは無用で、結果は私が欲しいものです提供します。これはリスト内包表記の良いユースケースですか?

繰り返しは良い解決策ですが、これを行うにはもっと慣れ親しんだ方法があるのでしょうか?

+0

何らかの理由で私の質問をもう一度編集できません。私は要素の順序を気にすることを忘れていました。 – Paolo

+0

毎日の使用では、私は提案された解決法を仲介する必要があります。 Gerrat'sはコンパクトですが、TokenMacGuyは明快で高速ですが、tyzのものは中間でコンパクトで速くありません。偉大な答えを感謝します。ジェラートの答えは私の元の意図に近いので、私はそれをチェックした。 – Paolo

答えて

5

あなたは行うことができます:

l.extend((i for i in (2,3,4) if i not in l)) 

を追加したリストが非一意である場合、この解決策はまだ動作します。

+0

追加する数字が一意でない場合、このコードは異なる結果になります。 (2,3,4,4) – HYRY

+0

@ user772649:可能性がある場合は、単に追加する数値のグループの周りに 'set'をラップするだけで解決します。 – Gerrat

+0

位置情報が重要でない場合はset()を使用します。 set()はシーケンスの順序を変更します。 – HYRY

3

副作用のためだけにリスト内包表記を使用することはお勧めしません。 3行バージョンには何も問題はありません。

lが本当に長くなる場合は、あなたがまたはリスト内包の有無にかかわらず、長いリスト

7

このアルゴリズムにin lを使用しないように平行に設定を維持したいことは、可能な限り効率的ではありません。 list.__contains__はO(n)なので、別のリストの要素を追加するにはO(n )です。一方、set.__contains__はO(log n)なので、が最も良い方法はです。メンバーシップをチェックするためにセットを使用し、順序を保存するためにリストを使用することです。そのようにして、合理的な値n(100要素以上)に対してO(n )よりずっと速いO(log n) 。

orig = [1,2] 
ext = [2,3,4] 
orig.extend(filter(lambda x,p=set(orig):not(x in p or p.add(x)),ext)) 

これは、アカウントの要素の順序を考慮に入れると、要素の繰り返しの場合に動作します:

>>> l = [1, 2] 
>>> seen = set(l) 
>>> for x in (2, 3, 4): 
...  if x not in seen: 
...   seen.add(x) 
...   l.append(x) 
... 
>>> l 
[1, 2, 3, 4] 
>>> 
+0

+1アルゴリズムの指定 – Kracekumar

3

私は1つの以上のソリューションを提案することができます。

ところで、複雑さはO(n * log(n))です。

+0

余分な賢さは、とにかく+1です。 – SingleNegationElimination

関連する問題