У багатьох випадках використання потрібна відповідь:
ys = set(y)
[item for item in x if item not in ys]
Це гібрид між відповіддю aaronasterling в і відповідь quantumSoup в .
Версія aaronasterling робить len(y)порівняння елементів для кожного елемента x, тому це займає квадратичний час. версія використовує набори quantumSoup, так що він робить одну постійного час набору пошуку для кожного елемента в xбуті, так як він перетворює як x іy в наборах, вона втрачає порядок ваших елементів.
Перетворюючи лише yнабір і повторюючи xпорядок, ви отримуєте найкраще з обох світів - лінійного часу та збереження порядку. *
Однак це все ще має проблему з версією QuantumSoup: Це вимагає, щоб ваші елементи були перебірними. Це в значній мірі вбудовано в природу множин. ** Якщо ви намагаєтесь, наприклад, відняти список диктовок з іншого списку диктів, але список для віднімання великий, що ви робите?
Якщо ви можете прикрасити свої цінності таким чином, щоб вони були зручними, це вирішить проблему. Наприклад, з плоским словником, значення якого самі є доступними:
ys = {tuple(item.items()) for item in y}
[item for item in x if tuple(item.items()) not in ys]
Якщо ваші типи трохи складніші (наприклад, часто ви маєте справу з сумісними з JSON значеннями, які є хешбек, або списками або диктантами, значення яких рекурсивно одного типу), ви все одно можете використовувати це рішення. Але деякі типи просто неможливо перетворити на що-небудь доступне.
Якщо ваші предмети не є і їх неможливо зробити хешируемими, але вони порівнянні, ви можете принаймні отримати лінійний час журналу ( O(N*log M)що набагато краще, ніж O(N*M)час рішення списку, але не так добре, як O(N+M)час заданого розчину) шляхом сортування і з допомогою 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)]
Якщо ваші предмети не є ні доступними, ні порівняльними, то ви застрягли в квадратичному рішенні.
* Зауважте, що ви могли також зробити це за допомогою пари OrderedSetоб'єктів, для яких ви можете знайти рецепти та сторонні модулі. Але я думаю, що це простіше.
** Причина, що шукає пошуки - це постійний час, полягає в тому, що все, що потрібно зробити, - це хеш-значення і подивитися, чи є запис для цього хешу. Якщо він не може хеш-значення, це не працюватиме.