2011-03-11 14 views
72

リスト内のすべての要素が一意であるかどうかをチェックする最良の方法(従来の方法と同じ) Counterを使用してリスト内のすべての要素が一意であるかどうかを確認する

私の現在のアプローチは、次のとおりです。

>>> x = [1, 1, 1, 2, 3, 4, 5, 6, 2] 
>>> counter = Counter(x) 
>>> for values in counter.itervalues(): 
     if values > 1: 
      # do something 

は、私が良くやることはできますか?

答えて

107

最も効率的な、しかし、まっすぐ進むと簡潔ない:

if len(x) > len(set(x)): 
    pass # do something 

はおそらく、短いリストの違いの多くをすることはありません。

+1

あなたは==を意味しますか? – Ant

+0

これも私がやっていることです。おそらく大規模なリストでは効率的ではありません。 – tkerwin

+0

リストに繰り返し要素がある場合(条件例の "#do something")、条件付きの本体が実行されるとは限りません。 – yan

6

すべてのエントリをセットに追加してその長さをチェックするのはどうですか?

len(set(x)) == len(x) 
+0

yan、auchの後に1秒後に答えました。短くて甘い。このソリューションを使用しない理由は何ですか? – jasonleonhard

9

setする代わりに、あなたはdictを使用することができます。

len({}.fromkeys(x)) == len(x) 
+1

本当に素晴らしいアイデア! +1 –

+4

私は、セットに対してdictを使うことに全く利点はないと思う。不必要に複雑なものに思えます。 – metasoarous

17

早期終了のソリューションは、小規模な例のためしかし

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))を期待します。

+0

+1これは効率的な方法です。 – tokland

+0

私は特に最適化を求めていないので、私は他の答えを受け入れました。 – user225312

+2

's = set()' ...の後ろに次の行を置くことでこれを短縮することができます。xがgでない場合は何も返しません(s.add(x)g内のxに対してTrue) ' –

0

あなたはヤンの構文を使用することができます(LEN(x)は> LEN(セットは、(X)))が、代わりにセットの(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

+0

良いかもしれませんが、私は最適化を探していません。 – user225312

+0

このf5関数は、スピードがよく最適化されたsetを使用するよりも遅くなります。このコードは、高価な「追加」操作のためにリストが実際に大きくなったときに中断し始めます。 'x = range(1000000)+ range(1000000)'のような大きなリストでは、set(x)を実行するとf5(x)より高速です。注文は質問の要件ではありませんが、sorted(set(x))を実行してもf5(x)よりも高速です – OkezieE

66

も早期終了を行います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 
+3

+1クリーンであり、必要でない場合はリスト全体を繰り返し処理しません。 – Kos

+0

+1、パーティーに遅れていますが、これは素晴らしい解決策です(さらに多くのアップフォースが必要です)。 –

+0

@ paul-mcguire:Apache 2.0互換のライセンス(Apache 2、2/3行のBSD、MIT、X11、zlibなど)でこのコードスニペットのライセンスを取得しますか?私が使用しているApache 2.0プロジェクトで使用したいのですが、StackOverflowのライセンス条項が_fubar_なので、元の作者としてお願いしています。 –

1

どのようにこの

についてスピードのための0
def is_unique(lst): 
    if not lst: 
     return True 
    else: 
     return Counter(lst).most_common(1)[0][1]==1 
11

:完全

import numpy as np 
x = [1, 1, 1, 2, 3, 4, 5, 6, 2] 
np.unique(x).size == len(x) 
1

別のアプローチ、ソートやGROUPBYを使用して:

from itertools import groupby 
is_unique = lambda seq: all(sum(1 for _ in x[1])==1 for x in groupby(sorted(seq))) 

をそれはソートが必要ですが、最初の繰り返し値で終了します。ここで

+0

ハッシングはソートより速い – IceArdor

2

は、再帰的な早期終了関数である:

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)  

が機能スタイルのアプローチを持ちながら、それは奇妙な(遅い)変換を使用せずに私のために十分な速さです。内容かどうかをテストするためにパンダのデータフレーム内の類似のアプローチを使用

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 
+1

'H in T'は線形検索を行い、' T = L [1:] 'はリストのスライスされた部分をコピーするので、これは他の解法よりもはるかに遅くなりますビッグリスト。他のほとんどはO(N)(集合)またはO(N log N)(ソートベースの解)ですが、O(N^2)と思います。 – Blckknght

1

は楽しみのために再帰O(N )バージョンであります列には一意の値が含まれています:

if tempDF['var1'].size == tempDF['var1'].unique().size: 
    print("Unique") 
else: 
    print("Not unique") 

私にとって、これは私ですnstantaneousは100万行を超える日付フレーム内のint変数です。

-4
def is_unique(lst): 
    if len(lst) > 1: 
     return is_unique(s[1:]) and (s[0] not in s[1:]) 
    return True 

:ここ

関連する問題