8

プログラムの一部として生成する Python のリストがあります。これらはすべて異なるという強い仮定があり、これをアサーションで確認します。

これは私が今やっている方法です:

2 つの要素がある場合:

try:
    assert(x[0] != x[1])
except:
    print debug_info
    raise Exception("throw to caller")

3 つある場合:

try:
    assert(x[0] != x[1])
    assert(x[0] != x[2])
    assert(x[1] != x[2])
except:
    print debug_info
    raise Exception("throw to caller")

そして、これを 4 つの要素で行う必要があるとしたら、気が狂ってしまいます。

リストのすべての要素が一意であることを確認するより良い方法はありますか?

4

7 に答える 7

26

多分このようなもの:

if len(x) == len(set(x)):
    print "all elements are unique"
else:
    print "elements are not unique"
于 2009-09-30T23:09:26.827 に答える
18

最も一般的な回答は O(N) (良い!-) ですが、@Paul と @Mark が指摘しているように、リストの項目がハッシュ可能である必要があります。@Paul と @Mark が提案した、ハッシュ不可能なアイテムに対するアプローチはどちらも一般的ですが、O(N 二乗) を必要とします。

リストのアイテムがハッシュ可能ではない比較可能である場合は、より適切に行うことができます...リストのアイテムの性質を考慮して、常に可能な限り速く機能するアプローチを次に示します。

import itertools

def allunique(L):
  # first try sets -- fastest, if all items are hashable
  try:
    return len(L) == len(set(L))
  except TypeError:
    pass
  # next, try sort -- second fastest, if items are comparable
  try:
    L1 = sorted(L)
  except TypeError:
    pass
  else:
    return all(len(list(g))==1 for k, g in itertools.groupby(L1))
  # fall back to the slowest but most general approach
  return all(v not in L[i+1:] for i, L in enumerate(L))

これは、実行可能な場合は O(N) (すべてのアイテムがハッシュ可能)、最も頻繁なフォールバックとして O(N log N) (一部のアイテムはハッシュ不可能ですが、すべて比較可能)、避けられない場合は O(N 二乗) (一部のアイテムはハッシュ不可能、例えば dicts、およびいくつかの比較できないもの、たとえば複素数)。

このコードのインスピレーションは、偉大なティム ピーターズによる古いレシピから来ています。これは、実際にユニークなアイテムのリストを生成することで異なります (また、これまでは存在しませんでした -- それは...!-setを使用する必要がありました)。dictしかし、基本的に同じ問題に直面しました。

于 2009-10-01T01:45:12.937 に答える
7

これはどう:

if len(x) != len(set(x)):
    raise Exception("throw to caller")

これは、の要素xがハッシュ可能であることを前提としています。

于 2009-09-30T23:11:09.333 に答える
2

シーケンス内のすべての項目が不変であることを願っています。そうでない場合は、シーケンスを呼び出すことができませんset

>>> set( ([1,2], [3,4]) )
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

変更可能なアイテムがある場合、アイテムをハッシュすることはできず、リストを繰り返しチェックする必要があります

def isUnique(lst):
    for i,v in enumerate(lst):
        if v in lst[i+1:]:
            return False
    return True

>>> isUnique( ([1,2], [3,4]) )
True
>>> isUnique( ([1,2], [3,4], [1,2]) )
False
于 2009-09-30T23:31:47.467 に答える
1

リストを作成するときに、値がすでに存在するかどうかを確認できます。たとえば、次のようになります。

if x in y:
     raise Exception("Value %s already in y" % x)
else:
     y.append(x)

これの利点は、衝突変数が報告されることです。

于 2009-09-30T23:40:31.707 に答える
0

リストを処理して、一意であることがわかっているコピーを作成できます。

def make_unique(seq): 
    t = type(seq) 
    seen = set()
    return t(c for c in seq if not (c in seen or seen.add(c)))

または、seq 要素がハッシュ可能でない場合:

def unique1(seq):
    t = type(seq) 
    seen = [] 
    return t(c for c in seq if not (c in seen or seen.append(c)))

これにより、アイテムが順番に保持されます(もちろん、重複は省略されます)。

于 2009-10-01T01:22:28.383 に答える
0

私はこれを使用します:

mylist = [1,2,3,4]
is_unique = all(mylist.count(x) == 1 for x in mylist)
于 2009-10-01T10:32:14.297 に答える