リスト内のすべての要素が一意であるかどうかを確認する最良の方法(従来の方法と同様)は何ですか?
私の現在のアプローチCounter
は次のとおりです:
>>> x = [1, 1, 1, 2, 3, 4, 5, 6, 2]
>>> counter = Counter(x)
>>> for values in counter.itervalues():
if values > 1:
# do something
もっと上手にできる?
リスト内のすべての要素が一意であるかどうかを確認する最良の方法(従来の方法と同様)は何ですか?
私の現在のアプローチ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
ショートリストの場合、おそらく違いはほとんどありません。
len(x) > len(set(x))
要素x
が一意でない場合はTrue です。この質問のタイトルは正反対の質問です。「リスト内のすべての要素が一意であるかどうかの確認」
これも早期終了を行う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))
最速の方法であることを期待します。
s = set()
...return not any(s.add(x) if x not in s else True for x in g)
len(x) != len(set(x))
早期終了が一般的でない場合に、これよりも高速になると予想される理由を説明できますか?両方の操作はO(len(x))ではありませんか?(x
元のリストはここにあります)
if x in s
内をチェックしているので、メソッドはO(len(x))ではありません。
すべてのエントリをセットに追加して、その長さをチェックするのはどうですか?
len(set(x)) == len(x)
len()
いるわけではありません。
の代わりにset
、を使用できますdict
。
len({}.fromkeys(x)) == len(x)
別のアプローチとして、sortedおよびgroupbyを使用します。
from itertools import groupby
is_unique = lambda seq: all(sum(1 for _ in x[1])==1 for x in groupby(sorted(seq)))
ソートが必要ですが、最初に繰り返された値で終了します。
groupby
答えを使用して同じソリューションを投稿するためにここに来て、この答えを見つけました。これは最もエレガントです。これは単一の式であり、追加の変数やループステートメントを必要とせずに組み込みツールで動作するためです。
id()
、これがための前提条件であるとして、それらをソートする機能をgroupby()
仕事に:groupby(sorted(seq), key=id)
再帰的な早期終了関数は次のとおりです。
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)
関数型のアプローチをとりながら、奇妙な(遅い)変換を使わなくても十分高速です。
H in T
線形検索を行いT = L[1:]
、リストのスライスされた部分をコピーするため、これは大きなリストで提案されている他のソリューションよりもはるかに遅くなります。それはO(N ^ 2)だと思いますが、他のほとんどはO(N)(セット)またはO(N log N)(並べ替えベースのソリューション)です。
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
x = range(1000000) + range(1000000)
、set(x)の実行はf5(x)よりも高速です。順序は問題ではありませんが、sorted(set(x))を実行してもf5(x)より高速です
Pandasデータフレームで同様のアプローチを使用して、列の内容に一意の値が含まれているかどうかをテストします。
if tempDF['var1'].size == tempDF['var1'].unique().size:
print("Unique")
else:
print("Not unique")
私にとって、これは100万行を超える日付フレームのint変数で瞬時に発生します。
上記のすべての答えは良いですが、私all_unique
は30秒のpythonの例を使用することを好みます
set()
重複を削除するには、指定されたリストで使用する必要があります。その長さとリストの長さを比較してください。
def all_unique(lst):
return len(lst) == len(set(lst))
True
フラットリストのすべての値がである場合に返されますunique
。False
それ以外の場合は
x = [1,2,3,4,5,6]
y = [1,2,2,3,4,5]
all_unique(x) # True
all_unique(y) # False
初心者向け:
def AllDifferent(s):
for i in range(len(s)):
for i2 in range(len(s)):
if i != i2:
if s[i] == s[i2]:
return False
return True