例えば:
>>> a
[2, -4, -2, 4, -3, -1, 3, 4, 2, 2]
>>> unique(a)
[2, 3, 4, -2, -4, -3, -1]
各値が 1 回だけ表示されるような値のリストが表示されますが、元のリストと同じ順序で出力したいと考えています。
例えば:
>>> a
[2, -4, -2, 4, -3, -1, 3, 4, 2, 2]
>>> unique(a)
[2, 3, 4, -2, -4, -3, -1]
各値が 1 回だけ表示されるような値のリストが表示されますが、元のリストと同じ順序で出力したいと考えています。
Aset
には順序がないため、リストをセットに変換した後、要素を反復するときの結果の順序は実装の詳細です。
を使用しOrderedDict
て、注文で一定の動作を取得できます。
>>> from collections import OrderedDict
>>> a = [2, -4, -2, 4, -3, -1, 3, 4, 2, 2]
>>> x = OrderedDict.fromkeys(a)
>>> list(x)
[2, -4, -2, 4, -3, -1, 3]
これは、基本的に元のリストの要素を繰り返し処理し、追加するリストにまだ含まれているかどうかを確認する、より高速な(コンパクトset
ではありませんが)アプローチです。私のアプローチをさらにスピードアップする可能性のあるいくつかの微妙な変更があるかもしれません:
def _order(orig):
ordset = set()
for x in orig:
if x in ordset:
continue
ordset.add(x)
yield x
def unique(orig):
return list(_order(orig))
出力:
>>> unique(a)
[2, -4, -2, 4, -3, -1, 3]
ベンチマーク:
>>> import timeit
>>> setup = '''
a = [2, -4, -2, 4, -3, -1, 3, 4, 2, 2]
from collections import OrderedDict
def unique():
x = OrderedDict.fromkeys(a)
return list(x)
'''
>>> print (min(timeit.Timer('unique()', setup=setup).repeat(100, 1000)))
0.031305141204512665
上記の答え:
>>> import timeit
>>> setup = '''
a = [2, -4, -2, 4, -3, -1, 3, 4, 2, 2]
def _order(orig):
ordset = set()
for x in orig:
if x in ordset:
continue
ordset.add(x)
yield x
def unique(orig):
return list(_order(orig))
'''
>>> print (min(timeit.Timer('unique(a)', setup=setup).repeat(100, 1000)))
0.0031761333803501657
このアプローチは、ほぼ 10 倍高速です。このような小さなリストの場合、違いはごくわずかであり、Poke の回答は素晴らしいものです。ただし、大規模なリスト (たとえば、10000 倍長いリスト) に対してこれを行った場合、5 秒と比較して 75 秒の差があります。