a = [1, 2, 3, 1, 2, 3]
b = [3, 2, 1, 3, 2, 1]
aとbは要素がまったく同じで、順序が異なるため、等しいと見なす必要があります。
実は、私の実際のリストは、整数ではなくオブジェクト(私のクラスインスタンス)で構成されています。
len()
最初にをチェックするかもしれません。
a = [1, 2, 3, 1, 2, 3]
b = [3, 2, 1, 3, 2, 1]
aとbは要素がまったく同じで、順序が異なるため、等しいと見なす必要があります。
実は、私の実際のリストは、整数ではなくオブジェクト(私のクラスインスタンス)で構成されています。
len()
最初にをチェックするかもしれません。
回答:
O(n):Counter()メソッドが最適です(オブジェクトがハッシュ可能な場合):
def compare(s, t):
return Counter(s) == Counter(t)
O(n log n):Sorted()メソッドが次に最適です(オブジェクトが順序付け可能な場合):
def compare(s, t):
return sorted(s) == sorted(t)
O(n * n):オブジェクトがハッシュ可能でも順序付け可能でもない場合は、等価を使用できます。
def compare(s, t):
t = list(t) # make a mutable copy
try:
for elem in s:
t.remove(elem)
except ValueError:
return False
return not t
sorted()
、確かに知りませんでしたCounter
。インタビュアーはもっと効率的な方法があると主張し、明らかに私は空白を描きました。timeit
モジュールを使用したpython 3での広範なテストの後、ソートされた整数のリストで一貫して速く出てきます。1k個のアイテムのリストでは、約1.5%遅く、短いリストでは、10個のアイテム、7.5%遅くなります。考え?
python3.6 -m timeit -s 'from collections import Counter' -s 'from random import shuffle' -s 't=list(range(100)) * 5' -s 'shuffle(t)' -s 'u=t[:]' -s 'shuffle(u)' 'Counter(t)==Counter(u)'
sorted vs counter
ました..ここで何が起こっているのか非常に興味があります。
両方を並べ替えることができます。
sorted(a) == sorted(b)
カウンティングソートはまた、より効率的かもしれない(しかし、それはハッシュ可能であることをオブジェクトが必要です)。
>>> from collections import Counter
>>> a = [1, 2, 3, 1, 2, 3]
>>> b = [3, 2, 1, 3, 2, 1]
>>> print (Counter(a) == Counter(b))
True
__hash__
、コレクションではそれが不可能な場合があります。
sorted([0, 1j])
これを行う最良の方法は、リストを並べ替えて比較することです。(Counter
ハッシュ化できないオブジェクトでは使用できません。)これは整数の場合は簡単です。
sorted(a) == sorted(b)
任意のオブジェクトでは少しトリッキーになります。オブジェクトの同一性、つまり同じオブジェクトが両方のリストにあるかどうかを気にする場合は、id()
関数を並べ替えキーとして使用できます。
sorted(a, key=id) == sorted(b, key==id)
(Python 2.xではkey=
、任意のオブジェクトを任意のオブジェクトと比較できるため、実際にはパラメーターは必要ありません。順序は任意ですが安定しているため、この目的のために正常に機能します。オブジェクトの順序は関係ありません。ただし、順序は両方のリストで同じです。ただし、Python 3では、さまざまなタイプのオブジェクトを比較することは、多くの状況で許可されていません。たとえば、文字列を整数と比較できないため、オブジェクトがある場合オブジェクトのIDを明示的に使用するのが最適です。)
一方、リスト内のオブジェクトを値で比較する場合は、最初にオブジェクトの「値」の意味を定義する必要があります。次に、それをキーとして(そしてPython 3の場合は一貫した型として)提供する方法が必要になります。多くの任意のオブジェクトで機能する1つの潜在的な方法は、それらのオブジェクトで並べ替えることrepr()
です。もちろん、これはrepr()
大きなリストなどのために多くの余分な時間とメモリ構築文字列を無駄にする可能性があります。
sorted(a, key=repr) == sorted(b, key==repr)
オブジェクトがすべて独自のタイプである場合は__lt__()
、オブジェクトを他のオブジェクトと比較する方法がわかるようにそれらを定義できます。次に、それらを並べ替えることができ、key=
パラメータについて心配する必要はありません。もちろん、を定義__hash__()
して使用することもできますCounter
。
https://docs.python.org/3.5/library/unittest.html#unittest.TestCase.assertCountEqual
assertCountEqual(最初、2番目、msg =なし)
順序に関係なく、最初にシーケンスに2番目と同じ要素が含まれていることをテストします。そうでない場合、シーケンス間の違いをリストするエラーメッセージが生成されます。
1番目と2番目を比較するときに、重複する要素は無視されません。各要素が両方のシーケンスで同じ数を持っているかどうかを確認します。assertEqual(Counter(list(first))、Counter(list(second)))と同等ですが、ハッシュ化できないオブジェクトのシーケンスでも機能します。
バージョン3.2の新機能。
または2.7:https : //docs.python.org/2.7/library/unittest.html#unittest.TestCase.assertItemsEqual
リストにハッシュ可能ではないアイテム(オブジェクトのリストなど)が含まれている場合は、Counter Classと次のようなid()関数を使用できる場合があります。
from collections import Counter
...
if Counter(map(id,a)) == Counter(map(id,b)):
print("Lists a and b contain the same objects")
比較をテストコンテキストで実行する場合は、assertCountEqual(a, b)
(py>=3.2
)およびassertItemsEqual(a, b)
(2.7<=py<3.2
)を使用します。
ハッシュ化できないオブジェクトのシーケンスでも機能します。
a、bリストとしましょう
def ass_equal(a,b):
try:
map(lambda x: a.pop(a.index(x)), b) # try to remove all the elements of b from a, on fail, throw exception
if len(a) == 0: # if a is empty, means that b has removed them all
return True
except:
return False # b failed to remove some items from a
それらをハッシュ可能にしたり、ソートしたりする必要はありません。
a
サポートpop
(変更可能)およびindex
(シーケンス)レイモンドはどちらも仮定しませんが、ニブラーはシーケンスのみを仮定します。