W wielu przypadkach użycia odpowiedź brzmi:
ys = set(y)
[item for item in x if item not in ys]
Jest to hybryda między odpowiedzią aaronasterling a odpowiedzią quantumSoup .
Wersja aaronasterlinga len(y)porównuje elementy dla każdego elementu x, więc zajmuje kwadratowy czas. Wersja quantumSoup używa zestawów, więc wykonuje pojedyncze wyszukiwanie zestawu w czasie stałym dla każdego elementu w x—Ale ponieważ konwertuje oba x i yna zestawy, traci kolejność elementów.
Konwertując tylko yna zbiór i iterując xpo kolei, otrzymujesz to, co najlepsze z obu światów - czas liniowy i zachowanie porządku. *
Jednak nadal ma to problem z wersją quantumSoup: wymaga, aby twoje elementy mogły być haszowalne. Jest to dość wbudowane w naturę zbiorów. ** Jeśli próbujesz np. Odjąć listę nagrań z innej listy nagrań, ale lista do odjęcia jest duża, co robisz?
Jeśli potrafisz udekorować swoje wartości w sposób umożliwiający ich haszowanie, rozwiąże to problem. Na przykład za pomocą płaskiego słownika, którego wartości same są haszowalne:
ys = {tuple(item.items()) for item in y}
[item for item in x if tuple(item.items()) not in ys]
Jeśli Twoje typy są nieco bardziej skomplikowane (np. Często masz do czynienia z wartościami kompatybilnymi z JSON, które są haszowalne, lub listami lub słownikami, których wartości są rekurencyjnie tego samego typu), możesz nadal korzystać z tego rozwiązania. Ale niektórych typów po prostu nie można przekształcić w nic, co da się mieszać.
Jeśli twoje przedmioty nie są i nie można ich utworzyć haszowalne, ale są porównywalne, możesz przynajmniej uzyskać log-liniowy czas ( O(N*log M)który jest znacznie lepszy niż O(N*M)czas rozwiązania listy, ale nie tak dobry jak O(N+M)czas zbioru roztworem) do sortowania i przy użyciu bisect:
ys = sorted(y)
def bisect_contains(seq, item):
index = bisect.bisect(seq, item)
return index < len(seq) and seq[index] == item
[item for item in x if bisect_contains(ys, item)]
Jeśli twoje przedmioty nie są haszowalne ani porównywalne, to utkniesz w kwadratowym rozwiązaniu.
* Pamiętaj, że możesz to również zrobić za pomocą pary OrderedSetobiektów, dla których możesz znaleźć przepisy i moduły innych firm. Ale myślę, że to jest prostsze.
** Powodem wyszukiwania zestawów jest stały czas, ponieważ wszystko, co musi zrobić, to haszować wartość i sprawdzić, czy istnieje wpis dla tego skrótu. Jeśli nie może uzyskać wartości skrótu, to nie zadziała.