Найти необычные элементы в списках

Я пытаюсь написать фрагмент кода, который может автоматически учитывать выражение. Например, если у меня есть два списка [1,2,3,4] и [2,3,5], код должен быть в состоянии найти общие элементы в двух списках [2,3] и объединить остальные элементы вместе в новом списке, будучи [1,4,5].

Из этого поста:Как найти пересечение списка? Я вижу, что общие элементы могут быть найдены

set([1,2,3,4]&set([2,3,5]). 

Есть ли простой способ извлечь необычные элементы из каждого списка, в моем примере это [1,4] и [5]?

Я могу пойти дальше и сделать цикл for:

lists = [[1,2,3,4],[2,3,5]]
conCommon = []
common = [2,3]
for elem in lists:
    for elem in eachList:
    if elem not in common:
        nonCommon += elem

Но это кажется излишним и неэффективным. Предоставляет ли Python удобную функцию, которая может это сделать? Заранее спасибо!!

 nye1705 июл. 2012 г., 18:46
Вы хотите получить отдельные списки типа [1,4] и [5] или один [1,4,5]?

Ответы на вопрос(4)

Вы можете использовать.__xor__ атрибутный метод.

set([1,2,3,4]).__xor__(set([2,3,5]))

или же

a = set([1,2,3,4])
b = set([2,3,5])
a.__xor__(b)
Решение Вопроса

sets (он же оператор XOR):

>>> set([1,2,3]) ^ set([3,4,5])
set([1, 2, 4, 5])
 turtlesoup05 июл. 2012 г., 18:14
о вау спасибо !! Bue ли приведенный выше код занимает равное количество времени вычислений и памяти, как установлено ([1,2,3]) и установлено ([3,4,5])? Или это не оказывает существенного влияния на производительность кода?
 05 июл. 2012 г., 18:17
Это самый эффективный способ достижения вашей цели. Его сложность находится в том же порядке, что и& (а именно, линейно по количеству элементов в наборах).

лем.

b1 = [1,2,3,4,5,9,11,15]
b2 = [4,5,6,7,8]
set(b1).intersection(b2)
Out[22]: {4, 5}

Лучшее в использовании этого кода - он работает довольно быстро и для больших данных. У меня есть b1 с 607139 и b2 с 296029 элементами, когда я использую эту логику, я получаю свои результаты за 2,9 секунды.

но похоже, что в Python есть встроенная функция, которая обеспечивает именно то, что вы ищете:.difference().

EXAMPLE

list_one = [1,2,3,4]
list_two = [2,3,5]

one_not_two = set(list_one).difference(list_two)
# set([1, 4])

two_not_one = set(list_two).difference(list_one)
# set([5])

Это также может быть записано как:

one_not_two = set(list_one) - set(list_two)

Timing

Я провел несколько тестов времени на обоих, и кажется, что.difference() имеет небольшое преимущество (10-15%), но каждый метод занимал около одной восьмой секунды, чтобы отфильтровать 1M элементов (случайные целые числа от 500 до 100 000), поэтому, если вы неvery чувствителен ко времени, это, вероятно, несущественно.

Other Notes

Похоже, что ОП ищет решение, которое предоставляет два отдельных списка (или набора) - один, где первый содержит элементы, а не второй, и наоборот. Большинство предыдущих ответов возвращают один список или набор, включающий все элементы.

Существует также вопрос относительно того, следует ли считать элементы, которые могут дублироваться в первом списке, несколько раз или только один раз.

Если ФП хочет сохранить дубликаты, может быть использовано понимание списка, например:

one_not_two = [ x for x in list_one if x not in list_two ]
two_not_one = [ x for x in list_two if x not in list_one ]

... что примерно такое же решение, как и в первоначальном вопросе, только немного чище. Этот метод будет поддерживать дубликаты из исходного списка, ноconsiderably (например, на несколько порядков) медленнее для больших наборов данных.

Ваш ответ на вопрос