リスト内のすべての要素が一意であるかどうかを確認する最良の方法(従来の方法と同様)は何ですか?
Counter
を使用した現在のアプローチは次のとおりです。
>>> x = [1, 1, 1, 2, 3, 4, 5, 6, 2]
>>> counter = Counter(x)
>>> for values in counter.itervalues():
if values > 1:
# do something
もっと良くできますか?
最も効率的ではありませんが、単純明快です:
if len(x) > len(set(x)):
pass # do something
おそらく、短いリストでは大きな違いはありません。
早期終了も行う2ライナーは次のとおりです。
>>> def allUnique(x):
... seen = set()
... return not any(i in seen or seen.add(i) for i in x)
...
>>> allUnique("ABCDEF")
True
>>> allUnique("ABACDEF")
False
Xの要素がハッシュ可能でない場合は、seen
のリストを使用する必要があります。
>>> def allUnique(x):
... seen = list()
... return not any(i in seen or seen.append(i) for i in x)
...
>>> allUnique([list("ABC"), list("DEF")])
True
>>> allUnique([list("ABC"), list("DEF"), list("ABC")])
False
早期終了ソリューションは
_def unique_values(g):
s = set()
for x in g:
if x in s: return False
s.add(x)
return True
_
ただし、小規模な場合や早期終了が一般的な場合ではない場合は、len(x) != len(set(x))
が最速の方法であることを期待します。
速度のために:
import numpy as np
x = [1, 1, 1, 2, 3, 4, 5, 6, 2]
np.unique(x).size == len(x)
セットにすべてのエントリを追加し、その長さをチェックするのはどうですか?
len(set(x)) == len(x)
set
の代わりに、dict
を使用できます。
len({}.fromkeys(x)) == len(x)
ソートおよびgroupbyを使用する完全に別のアプローチ:
from itertools import groupby
is_unique = lambda seq: all(sum(1 for _ in x[1])==1 for x in groupby(sorted(seq)))
並べ替えが必要ですが、最初の繰り返し値で終了します。
再帰的な早期終了関数は次のとおりです。
def distinct(L):
if len(L) == 2:
return L[0] != L[1]
H = L[0]
T = L[1:]
if (H in T):
return False
else:
return distinct(T)
機能的なスタイルのアプローチをしながら、奇妙な(遅い)変換を使用せずに十分に高速です。
再帰的なO(N2)楽しみのためのバージョン:
def is_unique(lst):
if len(lst) > 1:
return is_unique(s[1:]) and (s[0] not in s[1:])
return True
これはどう
def is_unique(lst):
if not lst:
return True
else:
return Counter(lst).most_common(1)[0][1]==1
Pandasデータフレームで同様のアプローチを使用して、列の内容に一意の値が含まれているかどうかをテストします。
if tempDF['var1'].size == tempDF['var1'].unique().size:
print("Unique")
else:
print("Not unique")
私にとって、これは100万行を超える日付フレームのint変数で瞬間的です。
Yanの構文(len(x)> len(set(x)))を使用できますが、set(x)の代わりに関数を定義します:
def f5(seq, idfun=None):
# order preserving
if idfun is None:
def idfun(x): return x
seen = {}
result = []
for item in seq:
marker = idfun(item)
# in old Python versions:
# if seen.has_key(marker)
# but in new ones:
if marker in seen: continue
seen[marker] = 1
result.append(item)
return result
len(x)> len(f5(x))を実行します。これは高速であり、順序も維持されます。
そこからコードが取得されます: http://www.peterbe.com/plog/uniqifiers-benchmark