a = [1, 2, 3, 1, 2, 3]
b = [3, 2, 1, 3, 2, 1]
a i b należy uważać za równe, ponieważ mają dokładnie te same elementy, tylko w różnej kolejności.
Rzecz w tym, że moje rzeczywiste listy będą składać się z obiektów (instancji moich klas), a nie liczb całkowitych.
python
algorithm
list
comparison
johndir
źródło
źródło
len()
najpierw sprawdzić .Odpowiedzi:
O (n) : Metoda Counter () jest najlepsza (jeśli twoje obiekty są haszowane):
O (n log n) : Metoda sortowana () jest następna w kolejności (jeśli obiekty można uporządkować):
O (n * n) : Jeśli obiekty nie są ani hashowalne, ani uporządkowane, możesz użyć równości:
źródło
sorted()
, wprawdzie nie wiedząc o tymCounter
. Ankieter nalegał, że jest bardziej skuteczna metoda i najwyraźniej wyciągnąłem lukę. Po obszernych testach w Pythonie 3 ztimeit
modułem posortowane konsekwentnie pojawiają się szybciej na listach liczb całkowitych. Na listach 1k pozycji, około 1,5% wolniej, a na krótkich listach 10 pozycji, 7,5% wolniej. Myśli?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
. Jestem bardzo ciekawy, co się tutaj dzieje.Możesz sortować zarówno:
Sortowanie przez zliczanie może być również bardziej wydajny (ale wymaga obiektu przeznaczonego do hashable).
źródło
__hash__
, ale w przypadku kolekcji może to być niemożliwe.sorted([0, 1j])
Jeśli wiesz, że elementy są zawsze haszowane, możesz użyć a,
Counter()
które jest O (n)Jeśli wiesz, że elementy są zawsze możliwe do sortowania, możesz użyć,
sorted()
które jest O (n log n)W ogólnym przypadku nie możesz polegać na możliwości sortowania lub na posiadaniu elementów, więc potrzebujesz takiego rozwiązania awaryjnego, które niestety jest O (n ^ 2)
źródło
Najlepszym sposobem na to jest sortowanie list i porównywanie ich. (Użycie
Counter
nie zadziała z obiektami, które nie są hashowane). Jest to proste w przypadku liczb całkowitych:Trochę trudniej jest z przypadkowymi obiektami. Jeśli zależy Ci na tożsamości obiektu, tj. Czy te same obiekty znajdują się na obu listach, możesz użyć
id()
funkcji jako klucza sortowania.(W Pythonie 2.x nie potrzebujesz tego
key=
parametru, ponieważ możesz porównać dowolny obiekt z dowolnym obiektem. Kolejność jest dowolna, ale stabilna, więc działa dobrze w tym celu; nie ma znaczenia, w jakiej kolejności są obiekty in, tylko że kolejność jest taka sama dla obu list. Jednak w Pythonie 3 porównywanie obiektów różnych typów jest w wielu przypadkach niedozwolone - na przykład nie możesz porównywać łańcuchów z liczbami całkowitymi - więc jeśli będziesz mieć obiekty różnych typów, najlepiej jawnie użyć identyfikatora obiektu).Z drugiej strony, jeśli chcesz porównać obiekty na liście według wartości , najpierw musisz zdefiniować, co oznacza „wartość” dla obiektów. Wtedy będziesz potrzebował jakiegoś sposobu, aby podać go jako klucz (a dla Pythona 3 jako spójny typ). Jednym z potencjalnych sposobów działania w przypadku wielu dowolnych obiektów jest sortowanie według ich
repr()
. Oczywiście może to zmarnować dużo dodatkowego czasu irepr()
ciągów budujących pamięć dla dużych list i tak dalej.Jeśli wszystkie obiekty są twoimi własnymi typami, możesz
__lt__()
na nich zdefiniować, aby obiekt wiedział, jak porównywać się z innymi. Następnie możesz je po prostu posortować i nie martwić się okey=
parametr. Oczywiście możesz także zdefiniować__hash__()
i użyćCounter
, co będzie szybsze.źródło
https://docs.python.org/3.5/library/unittest.html#unittest.TestCase.assertCountEqual
assertCountEqual (pierwszy, drugi, msg = brak)
Przetestuj, że sekwencja najpierw zawiera te same elementy, co druga, niezależnie od ich kolejności. Jeśli tak nie jest, zostanie wygenerowany komunikat o błędzie zawierający różnice między sekwencjami.
Powielone elementy nie są ignorowane podczas porównywania pierwszego i drugiego. Sprawdza, czy każdy element ma taką samą liczbę w obu sekwencjach. Równoważne z: assertEqual (Counter (lista (pierwsza)), Counter (lista (druga))), ale działa również z sekwencjami obiektów, których nie można zhashować.
Nowość w wersji 3.2.
lub w wersji 2.7: https://docs.python.org/2.7/library/unittest.html#unittest.TestCase.assertItemsEqual
źródło
Jeśli lista zawiera elementy, których nie można haszować (na przykład listę obiektów), możesz użyć klasy Counter i funkcji id (), takiej jak:
źródło
Mam nadzieję, że poniższy fragment kodu może działać w twoim przypadku: -
Zapewni to, że wszystkie elementy na obu listach
a
ib
są takie same, niezależnie od tego, czy są one w tej samej kolejności, czy nie.Dla lepszego zrozumienia zapoznaj się z moją odpowiedzią na to pytanie
źródło
Jeśli porównanie ma być przeprowadzone w kontekście testowym, użyj
assertCountEqual(a, b)
(py>=3.2
) iassertItemsEqual(a, b)
(2.7<=py<3.2
).Działa również na sekwencjach obiektów, których nie można zhashować.
źródło
Niech a, b wymienia
Nie ma potrzeby ich haszowania ani sortowania.
źródło
a
obsługujepop
(jest zmienny) iindex
(jest sekwencją). Raymond's nie zakłada żadnego, podczas gdy Gnibbler zakłada tylko sekwencję.Korzystanie z
unittest
modułu zapewnia przejrzyste i standardowe podejście.źródło