Python находит элементы в одном списке, которые не находятся в другом
Мне нужно сравнить два списка, чтобы создать новый список конкретных элементов, найденных в одном списке, но не в другом. Например:
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?
Ответы
Ответ 1
(1) Вы можете использовать NumPy setdiff1d
. Из ответа Chinny84, если вы заинтересованы в уникальных элементах, то:
import numpy as np
list_1 = ["a", "b", "c", "d", "e"]
list_2 = ["a", "f", "c", "m"]
main_list = np.setdiff1d(list_2,list_1)
(2) В противном случае используйте main_list = np.setdiff1d(list_2,list_1, assume_unique=True)
Оба ответа дадут вам ["f", "m"]
. Однако, если list_2 = ["a", "f", "c", "m", "m"]
, ответ (1) дает ["f", "m"]
, но ответ (2) дает ["f", "m", "m"]
(поскольку единственность каждого элемента в list_2
несущественна).
python numpy
Ответ 2
Вы можете использовать наборы:
main_list = list(set(list_2) - set(list_1))
Вывод:
>>> list_1=["a", "b", "c", "d", "e"]
>>> list_2=["a", "f", "c", "m"]
>>> set(list_2) - set(list_1)
set(['m', 'f'])
>>> list(set(list_2) - set(list_1))
['m', 'f']
В комментарии @JonClements, вот более простая версия:
>>> list_1=["a", "b", "c", "d", "e"]
>>> list_2=["a", "f", "c", "m"]
>>> list(set(list_2).difference(list_1))
['m', 'f']
Ответ 3
Не уверен, почему приведенные выше объяснения настолько сложны, когда у вас есть собственные доступные методы:
main_list = list(set(list_2)-set(list_1))
Ответ 4
Используйте понимание списка следующим образом:
main_list = [item for item in list_2 if item not in list_1]
Выход:
>>> list_1 = ["a", "b", "c", "d", "e"]
>>> list_2 = ["a", "f", "c", "m"]
>>>
>>> main_list = [item for item in list_2 if item not in list_1]
>>> main_list
['f', 'm']
Edit:
Как упомянуто в комментариях ниже, с большими списками, вышеупомянутое не является идеальным решением. В этом случае лучшим вариантом будет сначала преобразовать list_1
в set
:
set_1 = set(list_1) # this reduces the lookup time from O(n) to O(1)
main_list = [item for item in list_2 if item not in set_1]
Ответ 5
Если вам требуется однострочное решение (игнорирование импорта), для которого требуется только O(max(n, m))
работать для входов длиной n
и m
, а не O(n * m)
, вы можете сделать это с помощью модуль itertools
:
from itertools import filterfalse
main_list = list(filterfalse(set(list_1).__contains__, list_2))
Это использует функциональные функции, выполняющие функцию обратного вызова при построении, позволяя ему однажды создать обратный вызов и повторно использовать его для каждого элемента без необходимости его хранить где-нибудь (потому что filterfalse
хранит его внутри); список понятий и выражений генератора может это сделать, но это уродливо. †
Получает одинаковые результаты в одной строке:
main_list = [x for x in list_2 if x not in list_1]
со скоростью:
set_1 = set(list_1)
main_list = [x for x in list_2 if x not in set_1]
Конечно, если сравнения предназначены для позиционирования, то:
list_1 = [1, 2, 3]
list_2 = [2, 3, 4]
должен производить:
main_list = [2, 3, 4]
(потому что значение в list_2
имеет совпадение с одним и тем же индексом в list_1
), вы обязательно должны пойти с ответом Patrick, который не предусматривает временного list
или set
(даже если set
составляет примерно O(1)
, они имеют более высокий "постоянный" коэффициент за проверку, чем простые проверки равенства) и включает в себя O(min(n, m))
работу, меньшую, чем любой другой ответ, и если ваша проблема является позиционно чувствительным, является единственным правильным решением, когда соответствующие элементы появляются при несоответствующих смещениях.
†. То, как сделать одно и то же с пониманием списка как однострочного, было бы злоупотребление вложенным циклом для создания и кеширования значений в "крайнем" цикле, например:
main_list = [x for set_1 in (set(list_1),) for x in list_2 if x not in set_1]
что также дает незначительное преимущество в производительности на Python 3 (поскольку теперь set_1
локально привязан к коду понимания, а не просматривается из вложенной области для каждой проверки; на Python 2 это не имеет значения, поскольку Python 2 не использует закрытие для понимания списков, они работают в том же объеме, в котором они используются).
Ответ 6
main_list=[]
list_1=["a", "b", "c", "d", "e"]
list_2=["a", "f", "c", "m"]
for i in list_2:
if i not in list_1:
main_list.append(i)
print(main_list)
выход:
['f', 'm']
Ответ 7
Я бы zip
списки вместе, чтобы сравнить их элемент за элементом.
main_list = [b for a, b in zip(list1, list2) if a!= b]
Ответ 8
Если необходимо учитывать количество вхождений, вам, вероятно, нужно использовать что-то вроде collections.Counter
:
list_1=["a", "b", "c", "d", "e"]
list_2=["a", "f", "c", "m"]
from collections import Counter
cnt1 = Counter(list_1)
cnt2 = Counter(list_2)
final = [key for key, counts in cnt2.items() if cnt1.get(key, 0) != counts]
>>> final
['f', 'm']
Как и было обещано, это может также обрабатывать различное количество вхождений как "различие":
list_1=["a", "b", "c", "d", "e", 'a']
cnt1 = Counter(list_1)
cnt2 = Counter(list_2)
final = [key for key, counts in cnt2.items() if cnt1.get(key, 0) != counts]
>>> final
['a', 'f', 'm']
Ответ 9
Из ser1 удалите элементы, присутствующие в ser2.
вход
ser1 = pd.Series([1, 2, 3, 4, 5]) ser2 = pd.Series([4, 5, 6, 7, 8])
Решение
ser1 [~ ser1.isin(SER2)]
Ответ 10
Я использовал два метода, и я нашел один метод полезным по сравнению с другим. Вот мой ответ:
Мои входные данные:
crkmod_mpp = ['M13','M18','M19','M24']
testmod_mpp = ['M13','M14','M15','M16','M17','M18','M19','M20','M21','M22','M23','M24']
Method1: np.setdiff1d
Мне нравится этот подход, потому что он сохраняет позицию
test= list(np.setdiff1d(testmod_mpp,crkmod_mpp))
print(test)
['M15', 'M16', 'M22', 'M23', 'M20', 'M14', 'M17', 'M21']
Method2: хотя он дает тот же ответ, что и в Method1, но нарушает порядок
test = list(set(testmod_mpp).difference(set(crkmod_mpp)))
print(test)
['POA23', 'POA15', 'POA17', 'POA16', 'POA22', 'POA18', 'POA24', 'POA21']
Method1 np.setdiff1d
полностью соответствует моим требованиям.
Этот ответ для информации.