web-dev-qa-db-ja.com

2つの番号なしリストが等しいかどうかを確認

2つの順序なしのリストに同じ要素が含まれているかどうかを判断するための簡単(かつ迅速)な方法を探しています。

例えば:

['one', 'two', 'three'] == ['one', 'two', 'three'] :  true
['one', 'two', 'three'] == ['one', 'three', 'two'] :  true
['one', 'two', 'three'] == ['one', 'two', 'three', 'three'] :  false
['one', 'two', 'three'] == ['one', 'two', 'three', 'four'] :  false
['one', 'two', 'three'] == ['one', 'two', 'four'] :  false
['one', 'two', 'three'] == ['one'] :  false

私は地図を使わずにこれをやりたいと思っています。

210
Paul

Pythonには、(ハッシュ可能な)ものの順不同コレクション(setname__)用の組み込みデータ型があります。両方のリストをセットに変換すると、比較は順序付けられません。

set(x) == set(y)

setNAME _ に関するドキュメント


編集:@ mdwhatcottはあなたが重複をチェックしたいことを指摘している。 setname__はこれらを無視するので、各リストの項目数も追跡する同様のデータ構造が必要です。これは マルチセット と呼ばれます。標準ライブラリで最も良い近似は collections.Counter です。

>>> import collections
>>> compare = lambda x, y: collections.Counter(x) == collections.Counter(y)
>>> 
>>> compare([1,2,3], [1,2,3,3])
False
>>> compare([1,2,3], [1,2,3])
True
>>> compare([1,2,3,3], [1,2,2,3])
False
>>> 
375
Katriel

要素がいつもあなたの例のようにほぼソートされているならば、組み込みの.sort()timsort )は速いはずです:

>>> a = [1,1,2]
>>> b = [1,2,2]
>>> a.sort()
>>> b.sort()
>>> a == b
False

インプレースソートをしたくない場合は、 sorted() を使うことができます。

実際には(漸近的にはcollections.Counter()時間がO(n)よりO(n*log(n))より優れているにもかかわらず)常に.sort()より速いかもしれません。測定するそれが重要ならば。

63
jfs
sorted(x) == sorted(y)

ここからコピーする: 2つの番号なしリストが等しいかどうかをチェックしてください

私はこれがこの質問に対する最良の答えだと思います

  1. この答え で指摘されているようにcounterを使うよりはましです
  2. x.sort()はxをソートします。これは副作用です。 sorted(x)は新しいリストを返します。
17
Enzam Hossain

それらに同じ要素が含まれているかどうかを確認したいのですが、順序を気にする必要はありません。

あなたはセットを使うことができます:

>>> set(['one', 'two', 'three']) == set(['two', 'one', 'three'])
True

しかし、集合オブジェクト自体には、それぞれの固有値のインスタンスが1つだけ含まれ、順序は維持されません。

>>> set(['one', 'one', 'one']) == set(['one'])
True

そのため、重複/長さを追跡することが重要な場合は、おそらく長さも確認する必要があります。

def are_eq(a, b):
    return set(a) == set(b) and len(a) == len(b)
14
Matimus

abがあなたのリストであるとすると、以下は一致する要素の数を返します(順序を考慮します).

sum([1 for i,j in Zip(a,b) if i==j])

したがって、

len(a)==len(b) and len(a)==sum([1 for i,j in Zip(a,b) if i==j])

両方のリストが同じで、同じ要素を同じ順序で含む場合はTrueになります。それ以外の場合はFalse

そのため、上記の最初の応答のように、コレクションライブラリなしでcompare関数を定義できます。

compare = lambda a,b: len(a)==len(b) and len(a)==sum([1 for i,j in Zip(a,b) if i==j])

そして

>>> compare([1,2,3], [1,2,3,3])
False
>>> compare([1,2,3], [1,2,3])
True
>>> compare([1,2,3], [1,2,4])
False
4
fiacobelli

上記の質問に対する裏書きの1つの回答は、次のとおりです。 -

2つのリストをlist1とlist2にします。2つのリストに同じ要素が含まれているかどうかを確認することが必要です。その場合は、私にとっては次の方法が最適です。

if ((len(list1) == len(list2)) and
   (all(i in list2 for i in list1))):
    print 'True'
else:
    print 'False'

上記のコードは、list1のすべての要素がlist2に含まれているかどうか、またその逆であるかどうかに応じて機能します。

ただし、list1のすべての要素がlist2に存在するかどうかを確認するだけの場合は、次のコードを使用する必要があります。 -

if all(i in list2 for i in list1):
    print 'True'
else:
    print 'False'

違いは、list2にlist1のすべての要素とともに余分な要素が含まれている場合、後者はTrueを出力するということです。つまり、list2に余分な要素があるかどうかにかかわらず、list1のすべての要素がlist2に存在するようになります。

3
Pabitra Pati

リストの文字列表現を取得してそれらを比較するのはどうでしょうか。

>>> l1 = ['one', 'two', 'three']
>>> l2 = ['one', 'two', 'three']
>>> l3 = ['one', 'three', 'two']
>>> print str(l1) == str(l2)
True
>>> print str(l1) == str(l3)
False
3
sagi

リストが同じサイズであることをすでに知っていると仮定すると、2つのベクトルが(順序を含めて)完全に同じである場合に限り、以下はTrueを保証します。

functools.reduce(lambda b1,b2: b1 and b2, map(lambda e1,e2: e1==e2, listA, ListB), True)

例:

>>> from functools import reduce
>>> def compvecs(a,b):
...     return reduce(lambda b1,b2: b1 and b2, map(lambda e1,e2: e1==e2, a, b), True)
... 
>>> compvecs(a=[1,2,3,4], b=[1,2,4,3])
False
>>> compvecs(a=[1,2,3,4], b=[1,2,3,4])
True
>>> compvecs(a=[1,2,3,4], b=[1,2,4,3])
False
>>> compare_vectors(a=[1,2,3,4], b=[1,2,2,4])
False
>>> 
3
Arnon Sela