Подтвердить что ты не робот

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?

4b9b3361

Ответ 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 несущественна).

Ответ 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 полностью соответствует моим требованиям. Этот ответ для информации.