2012-05-11 3 views
10

リスト内包表記を使用してリストから重複アイテムを削除するにはどうすればよいですか?私は次のコードを持っています:リスト内包表記を使用してリストから重複アイテムを削除するにはどうすればよいですか?

a = [1, 2, 3, 3, 5, 9, 6, 2, 8, 5, 2, 3, 5, 7, 3, 5, 8] 
b = [] 
b = [item for item in a if item not in b] 

しかし、それは動作しません、同じリストを生成します。なぜそれが同じリストを作り出しているのですか?

+4

「bがnot in bである」を実行する瞬間に 'b'が空であるため、リスト内包はメモリ内で行われ、結果は最後に「b」に割り当てられます。 –

+0

[アルゴリズム - リスト内の重複した要素を効率的に削除するには?](http://stackoverflow.com/questions/1801459/algorithm-how-to-delete-duplicate-elements-in-a-list-efficiently ) –

+0

つまり、リストの理解はループのようには機能しません。 – Alinwndrld

答えて

13

は、実行時に要素が含まれていません。リストが変更されていないことを理由にbが空を開始することである

>>> a = [1, 2, 3, 3, 5, 9, 6, 2, 8, 5, 2, 3, 5, 7, 3, 5, 8] 
>>> b = [] 
>>> [b.append(item) for item in a if item not in b] 
[None, None, None, None, None, None, None, None] 
>>> b 
[1, 2, 3, 5, 9, 6, 8, 7] 
+14

[副作用のためにリスト内包を使用する](http://stackoverflow.com/q/5753597/566644)に注意してください。代わりに、通常のforループを使用してください。 –

7

あなたはリスト内包とは異なる技術を使用して気にしない場合は、そのためのセットを使用することができます

>>> a = [1, 2, 3, 3, 5, 9, 6, 2, 8, 5, 2, 3, 5, 7, 3, 5, 8] 
>>> b = list(set(a)) 
>>> print b 
[1, 2, 3, 5, 6, 7, 8, 9] 
+0

私はset関数を見てきましたが、上記のコードに何が間違っているのかを知りたいのですが、それを修正できるのでしょうか? – Alinwndrld

+2

セットは最初の注文を維持しません...そのことに気をつけてください。 –

3

利用keysdict上のそのキーとしてa内の値で構成します。

b = dict([(i, 1) for i in a]).keys() 

またはSET使用:それはbとして、同一のリストを生成だ

b = [i for i in set(a)] 
4

:あなたはそれがこのほしいと何 。つまり、if item not in bは常にTrueです。リストが生成された後でなければ、変数bに割り当てられたこの新しい空でないリストが作成されます。

+1

正しく理解すれば、リスト内包は、ループのように各アイテムを一度に1つずつチェックして追加するのではなく、1つのアイテムを追加することを意味します。 – Alinwndrld

+1

@Alinwndrld:私はそれが有効な結論だとは思わない。これは、リストの理解度が割り当て前に評価されることを意味します。リストは内部的にループで構築されているかもしれません。 –

2

使用groupby:あなたは、例えば、値が最初に元のリストに登場する順序を気にしない場合

>>> from itertools import groupby 
>>> a = [1, 2, 3, 3, 5, 9, 6, 2, 8, 5, 2, 3, 5, 7, 3, 5, 8] 
>>> [k for k, _ in groupby(sorted(a, key=lambda x: a.index(x)))] 
[1, 2, 3, 5, 9, 6, 8, 7] 

は、キー引数を省略

>>> [k for k, _ in groupby(sorted(a))] 
[1, 2, 3, 5, 6, 7, 8, 9] 

groupbyでいくつかクールなことができます。

>>> [k for k, v in groupby(sorted(a)) if len(list(v)) > 1] 
[2, 3, 5, 8] 

または周波数辞書を構築する:複数回表示される項目を識別するために、

>>> {k: len(list(v)) for k, v in groupby(sorted(a))} 
{1: 1, 2: 3, 3: 4, 5: 4, 6: 1, 7: 1, 8: 2, 9: 1} 

itertoolsモジュール内のいくつかの非常に便利な機能があります:chainteeproductは少数に名前を付けるには、 !

1
>>> a = [10,20,30,20,10,50,60,40,80,50,40,0,100,30,60] 
>>> [a.pop(a.index(i, a.index(i)+1)) for i in a if a.count(i) > 1] 
>>> print(a)