Мне нужно сравнить два списка, чтобы создать новый список конкретных элементов, найденных в одном списке, но не найденных в другом. Например:
main_list=[]
list_1=["a", "b", "c", "d", "e"]
list_2=["a", "f", "c", "m"]
Я хочу перебрать list_1 и добавить в main_list все элементы из list_2, которых нет в list_1.
Результат должен быть:
main_list=["f", "m"]
Как я могу это сделать с помощью Python?
list_2
которые нигде не появляются,list_1
или элементыlist_2
, которых нет в том же индексеlist_1
?Ответы:
TL; DR:
РЕШЕНИЕ (1)
РЕШЕНИЕ (2) Вам нужен отсортированный список
ПОЯСНЕНИЕ:
(1) Вы можете использовать NumPy - х
setdiff1d
(array1
,array2
,assume_unique
=False
).assume_unique
спрашивает пользователя, УЖЕ УНИКАЛЬНЫЕ массивы.Если
False
, то сначала определяются уникальные элементы.Если
True
функция будет считать, что элементы уже уникальны, и функция пропустит определение уникальных элементов.Это дает уникальные значения
array1
, которых нет вarray2
.assume_unique
этоFalse
по умолчанию.Если вас интересуют уникальные элементы (на основе ответа Chinny84 ), просто используйте (где
assume_unique=False
=> значение по умолчанию):(2) Для тех, кто хочет отсортировать ответы, я создал специальную функцию:
Чтобы получить ответ, запустите:
ПОБОЧНЫЕ ЗАМЕЧАНИЯ:
(a) Решение 2 (пользовательская функция
setdiff_sorted
) возвращает список (по сравнению с массивом в решении 1).(b) Если вы не уверены, уникальны ли элементы, просто используйте настройку NumPy по умолчанию
setdiff1d
в обоих решениях A и B. Что может быть примером сложности? См. Примечание (c).(c) Все будет по-другому, если любой из двух списков не уникален.
Скажем
list_2
не уникальна:list2 = ["a", "f", "c", "m", "m"]
. Сохранитьlist1
как есть:list_1 = ["a", "b", "c", "d", "e"]
установка значения
assume_unique
урожайности по умолчанию["f", "m"]
(в обоих решениях). ОДНАКО, если вы установитеassume_unique=True
, оба решения дают["f", "m", "m"]
. Зачем? Это потому, что пользователь ПРЕДПОЛОЖИЛ, что элементы уникальны). Значит, ЛУЧШЕ СОХРАНИТЬassume_unique
значение по умолчанию. Обратите внимание, что оба ответа отсортированы.питонNumPy
источник
Можно использовать наборы:
Вывод:
Согласно комментарию @JonClements, вот более аккуратная версия:
источник
unique
элементах, но что, если у нас их несколько,m's
например, это не подберет его.list(set(list_2).difference(list_1))
избежать явногоset
преобразования ...Не уверен, почему приведенные выше объяснения настолько сложны, когда у вас есть собственные методы:
источник
Используйте понимание списка следующим образом:
Вывод:
Редактировать:
Как упоминалось в комментариях ниже, с большими списками вышесказанное не является идеальным решением. В таком случае лучшим вариантом будет преобразование
list_1
вset
первое:источник
list_1
вам нужно предварительно преобразовать его вset
/frozenset
, напримерset_1 = frozenset(list_1)
, затемmain_list = [item for item in list_2 if item not in set_1]
сократить время проверки сO(n)
каждого элемента до (примерно)O(1)
.enumerate()
для этого:[index for (index, item) in enumerate(list_2) if item not in list_1]
Если вам нужно однострочное решение (без учета импорта), которое требует
O(max(n, m))
работы только для входных данных длиныn
иm
неO(n * m)
работает, вы можете сделать это с помощьюitertools
модуля :При этом используются преимущества функциональных функций, принимающих функцию обратного вызова при построении, что позволяет ему создать обратный вызов один раз и повторно использовать его для каждого элемента без необходимости его где-то хранить (потому что
filterfalse
сохраняет его внутри); понимание списков и выражения генератора могут сделать это, но это некрасиво. †Это дает те же результаты в одной строке, что и:
со скоростью:
Конечно, если сравнения должны быть позиционными, поэтому:
должен производить:
(поскольку ни одно значение в не
list_2
имеет совпадения с тем же индексом вlist_1
), вам обязательно следует пойти с ответом Патрика , который не включает временныхlist
s илиset
s (даже еслиset
s примерноO(1)
, они имеют более высокий «постоянный» коэффициент на проверку, чем простое равенство проверяет) и требуетO(min(n, m))
работы, меньше, чем любой другой ответ, и если ваша проблема зависит от позиции, это единственное правильное решение, когда совпадающие элементы появляются с несоответствующими смещениями.†: способ сделать то же самое с пониманием списка как однострочным - это злоупотребить вложенным циклом для создания и кеширования значения (значений) в "внешнем" цикле, например:
что также дает незначительное преимущество в производительности на Python 3 (потому что теперь
set_1
локальная область видимости в коде понимания, а не поиск из вложенной области для каждой проверки; на Python 2 это не имеет значения, потому что Python 2 не использует замыкания для списки; они работают в той же области, в которой используются).источник
вывод:
источник
list_1
оно велико, иlist_2
имеет нетривиальный размер, потому что оно включаетlen(list_2)
O(n)
сканированиеlist_1
, созданиеO(n * m)
(гдеn
иm
- длиныlist_2
иlist_1
соответственно). Если вы конвертируетеlist_1
вset
/frozenset
заранее, проверки содержания могут быть выполнены вO(1)
, делая общую работуO(n)
над длинойlist_2
(техническиO(max(n, m))
, поскольку вы действительноO(m)
работаете над созданиемset
).Я бы
zip
собрал списки, чтобы сравнить их элемент за элементом.источник
list
s с одним созданным новымlist
, без дополнительных временных модулей , никаких дорогостоящих проверок содержания и т. д.Я использовал два метода и обнаружил, что один из них полезнее другого. Вот мой ответ:
Мои входные данные:
Метод 1:
np.setdiff1d
мне нравится этот подход по сравнению с другим, потому что он сохраняет позициюМетод 2: Хотя он дает тот же ответ, что и метод 1, но нарушает порядок
Method1 полностью
np.setdiff1d
соответствует моим требованиям. Это ответ для информации.источник
Если нужно учитывать количество повторов, вам, вероятно, нужно использовать что-то вроде
collections.Counter
:Как и было обещано, это также может обрабатывать различное количество вхождений как "разницу":
источник
Из ser1 удалите элементы, присутствующие в ser2.
вход
ser1 = pd.Series ([1, 2, 3, 4, 5]) ser2 = pd.Series ([4, 5, 6, 7, 8])
Решение
ser1 [~ ser1.isin (SER2)]
источник