Получить различия между двумя списками с уникальными элементами
У меня есть два списка в Python:
temp1 = ['One', 'Two', 'Three', 'Four']
temp2 = ['One', 'Two']
Предполагая, что элементы в каждом списке уникальны, я хочу создать третий список, который будет содержать элементы из первого списка, которые не присутствуют во втором списке:
temp3 = ['Three', 'Four']
Существуют ли быстрые способы сделать это без использования циклов и проверок?
5 ответ(ов)
Чтобы получить элементы, которые есть в temp1
, но отсутствуют в temp2
(предполагая уникальность элементов в каждом списке), вы можете воспользоваться следующим способом:
list(set(temp1) - set(temp2))
На выходе вы получите:
Out: ['Four', 'Three']
Обратите внимание, что операция асимметрична:
set([1, 2]) - set([2, 3])
Вернет:
Out: set([1])
Это может быть неожиданным, если вы ожидали получить set([1, 3])
. Если вам необходимо получить именно set([1, 3])
, вы можете воспользоваться методом симметричной разности:
set([1, 2]).symmetric_difference(set([2, 3]))
Существующие решения предлагают либо одно, либо другое:
- Производительность быстрее O(n*m).
- Сохранение порядка входного списка.
Однако до сих пор ни одно решение не сочетает оба этих преимущества. Если вам нужно и то, и другое, попробуйте следующее:
s = set(temp2)
temp3 = [x for x in temp1 if x not in s]
Тест производительности
import timeit
init = 'temp1 = list(range(100)); temp2 = [i * 2 for i in range(50)]'
print(timeit.timeit('list(set(temp1) - set(temp2))', init, number=100000))
print(timeit.timeit('s = set(temp2); [x for x in temp1 if x not in s]', init, number=100000))
print(timeit.timeit('[item for item in temp1 if item not in temp2]', init, number=100000))
Результаты:
4.34620224079 # ответ ars
4.2770634955 # этот ответ
30.7715615392 # ответ matt b
Метод, который я представил, не только сохраняет порядок, но и (немного) быстрее, чем вычитание множеств, так как не требует создания лишнего множества. Разница в производительности была бы более заметной, если первый список значительно длиннее второго и если хеширование затратное. Вот второе тестирование, демонстрирующее это:
init = '''
temp1 = [str(i) for i in range(100000)]
temp2 = [str(i * 2) for i in range(50)]
'''
Результаты:
11.3836875916 # ответ ars
3.63890368748 # этот ответ (в 3 раза быстрее!)
37.7445402279 # ответ matt b
Это можно сделать с использованием оператора XOR в Python.
- Это удалит дубликаты в каждом списке.
- Это покажет разницу между
temp1
иtemp2
, а также междуtemp2
иtemp1
.
set(temp1) ^ set(temp2)
Вы можете использовать генерацию списков:
temp3 = [item for item in temp1 if item not in temp2]
Попробуйте сделать так:
temp3 = set(temp1) - set(temp2)
Этот код создаст temp3
, содержащий элементы, которые есть в temp1
, но отсутствуют в temp2
. Использование множеств (set) позволяет эффективно выполнять операции разности между ними.
Самый быстрый способ проверить наличие значения в списке
Как получить последний элемент списка?
Как клонировать список, чтобы он не изменялся неожиданно после присваивания?
Сравнение: генераторы списков против lambda + filter
Как отсортировать список/кортеж списков/кортежей по элементу на заданном индексе