Obter diferença entre duas listas

810

Eu tenho duas listas em Python, como estas:

temp1 = ['One', 'Two', 'Three', 'Four']
temp2 = ['One', 'Two']

Preciso criar uma terceira lista com itens da primeira lista que não estão presentes na segunda. Do exemplo que tenho que obter:

temp3 = ['Three', 'Four']

Existem maneiras rápidas sem ciclos e verificação?

Max Frai
fonte
14
Os elementos são garantidos exclusivos? Se você tem temp1 = ['One', 'One', 'One']e temp2 = ['One']deseja ['One', 'One']voltar, ou []?
Michael Mrozek
@ Michael-mrozek eles são únicos.
Max Frai
12
Deseja preservar a ordem dos elementos?
precisa

Respostas:

1209
In [5]: list(set(temp1) - set(temp2))
Out[5]: ['Four', 'Three']

Cuidado que

In [5]: set([1, 2]) - set([2, 3])
Out[5]: set([1]) 

onde você pode esperar / querer que seja igual set([1, 3]). Se você quiser set([1, 3])como sua resposta, precisará usá-lo set([1, 2]).symmetric_difference(set([2, 3])).

ars
fonte
27
@Drewdin: As listas não suportam o operando "-". Define, no entanto, e o que é demonstrado acima, se você olhar atentamente.
Godsmith 14/10
1
Obrigado, acabei usando set (ListA) .symmetric_difference (ListB) #
1100 Drewdin
43
diferença simétrica pode ser escrito com: ^ (set1 ^ set2)
Bastian
10
Por favor, você poderia editar sua resposta e apontar que isso retorna apenas o temp1-temp2? .. Como outro disse para voltar todas as diferenças que você tem que usar a diferença SYSMETRIC: list (set (temp1) ^ set (temp2))
rkachach
Por que eu recebo TypeError: 'str' object is not callablequando eu executar esta operação a = [1,2,2,2,3]eb = [2]
d8aninja
477

Todas as soluções existentes oferecem um ou outro de:

  • Desempenho mais rápido que O (n * m).
  • Preservar a ordem da lista de entrada.

Mas até agora nenhuma solução tem os dois. Se você quer os dois, tente o seguinte:

s = set(temp2)
temp3 = [x for x in temp1 if x not in s]

Teste de performance

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)

Resultados:

4.34620224079 # ars' answer
4.2770634955  # This answer
30.7715615392 # matt b's answer

O método que apresentei, além de preservar a ordem, também é (um pouco) mais rápido que a subtração do conjunto, pois não requer a construção de um conjunto desnecessário. A diferença de desempenho seria mais perceptível se a primeira lista for consideravelmente maior que a segunda e se o hash for caro. Aqui está um segundo teste demonstrando isso:

init = '''
temp1 = [str(i) for i in range(100000)]
temp2 = [str(i * 2) for i in range(50)]
'''

Resultados:

11.3836875916 # ars' answer
3.63890368748 # this answer (3 times faster!)
37.7445402279 # matt b's answer
Mark Byers
fonte
2
Suporte adicional para esta resposta: deparei com um caso de uso em que preservar a ordem da lista era importante para o desempenho. Ao trabalhar com objetos tarinfo ou zipinfo, eu estava usando subtração de conjunto. Para excluir certos objetos tarinfo da extração do arquivo morto. A criação da nova lista foi rápida, mas super lenta durante a extração. A razão me escapou no começo. Acontece que reordenar a lista de objetos tarinfo causou uma enorme penalidade de desempenho. A mudança para o método de compreensão da lista salvou o dia.
Ray Thompson
@ MarkByers - talvez eu deva escrever uma pergunta totalmente nova para isso. Mas como isso funcionaria rapidamente? Por exemplo, se meu temp1 e temp2 continuam mudando .. e eu quero acrescentar as novas informações ao temp3?
Ason
@ MarkByers - parece bom. Vou continuar pensando um pouco. mas +1 para uma ótima solução.
Ason
Concordo com @Dejel >>> temp1 = ['Um', 'Dois', 'Três', 'Quatro'] >>> temp2 = ['Um', 'Dois', 'Seis'] >>> s = set (temp2) >>> temp3 = [x para x em temp1 se x não estiver em s] >>> temp3 ['Três', 'Quatro'] #
earlonrails
3
@haccks Como verificar a associação de uma lista é uma operação O (n) (repetindo a lista inteira), mas verificar a associação de um conjunto é O (1).
Mark Byers
86
temp3 = [item for item in temp1 if item not in temp2]
matt b
fonte
15
Transformar-se temp2em um conjunto antes tornaria isso um pouco mais eficiente.
lunaryorn
3
É verdade, depende se Ockonal preocupações sobre duplicatas ou não (pergunta original não diz)
matt b
2
O comentário diz que as (listas | tuplas) não têm duplicatas.
1
Votei sua resposta porque achei que você estava certo quanto às duplicatas em primeiro lugar. Mas item not in temp2e item not in set(temp2)sempre retornará os mesmos resultados, independentemente de haver duplicatas ou não temp2.
arekolek
5
Voto positivo por não exigir que os itens da lista sejam laváveis.
Brent
23

A diferença entre duas listas (por exemplo, lista1 e lista2) pode ser encontrada usando a seguinte função simples.

def diff(list1, list2):
    c = set(list1).union(set(list2))  # or c = set(list1) | set(list2)
    d = set(list1).intersection(set(list2))  # or d = set(list1) & set(list2)
    return list(c - d)

ou

def diff(list1, list2):
    return list(set(list1).symmetric_difference(set(list2)))  # or return list(set(list1) ^ set(list2))

Usando a função acima, a diferença pode ser encontrada usando diff(temp2, temp1)ou diff(temp1, temp2). Ambos vão dar o resultado ['Four', 'Three']. Você não precisa se preocupar com a ordem da lista ou com qual lista deve ser fornecida primeiro.

Referência do Documento Python

arulmr
fonte
7
Por que não definir (list1) .symmetric_difference (set (list2))?
swietyy
20

Caso você queira a diferença recursivamente, escrevi um pacote para python: https://github.com/seperman/deepdiff

Instalação

Instale a partir do PyPi:

pip install deepdiff

Exemplo de uso

Importando

>>> from deepdiff import DeepDiff
>>> from pprint import pprint
>>> from __future__ import print_function # In case running on Python 2

O mesmo objeto retorna vazio

>>> t1 = {1:1, 2:2, 3:3}
>>> t2 = t1
>>> print(DeepDiff(t1, t2))
{}

O tipo de um item foi alterado

>>> t1 = {1:1, 2:2, 3:3}
>>> t2 = {1:1, 2:"2", 3:3}
>>> pprint(DeepDiff(t1, t2), indent=2)
{ 'type_changes': { 'root[2]': { 'newtype': <class 'str'>,
                                 'newvalue': '2',
                                 'oldtype': <class 'int'>,
                                 'oldvalue': 2}}}

O valor de um item foi alterado

>>> t1 = {1:1, 2:2, 3:3}
>>> t2 = {1:1, 2:4, 3:3}
>>> pprint(DeepDiff(t1, t2), indent=2)
{'values_changed': {'root[2]': {'newvalue': 4, 'oldvalue': 2}}}

Item adicionado e / ou removido

>>> t1 = {1:1, 2:2, 3:3, 4:4}
>>> t2 = {1:1, 2:4, 3:3, 5:5, 6:6}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff)
{'dic_item_added': ['root[5]', 'root[6]'],
 'dic_item_removed': ['root[4]'],
 'values_changed': {'root[2]': {'newvalue': 4, 'oldvalue': 2}}}

Diferença de cadeia

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":"world"}}
>>> t2 = {1:1, 2:4, 3:3, 4:{"a":"hello", "b":"world!"}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff, indent = 2)
{ 'values_changed': { 'root[2]': {'newvalue': 4, 'oldvalue': 2},
                      "root[4]['b']": { 'newvalue': 'world!',
                                        'oldvalue': 'world'}}}

Diferença de cadeia 2

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":"world!\nGoodbye!\n1\n2\nEnd"}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":"world\n1\n2\nEnd"}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff, indent = 2)
{ 'values_changed': { "root[4]['b']": { 'diff': '--- \n'
                                                '+++ \n'
                                                '@@ -1,5 +1,4 @@\n'
                                                '-world!\n'
                                                '-Goodbye!\n'
                                                '+world\n'
                                                ' 1\n'
                                                ' 2\n'
                                                ' End',
                                        'newvalue': 'world\n1\n2\nEnd',
                                        'oldvalue': 'world!\n'
                                                    'Goodbye!\n'
                                                    '1\n'
                                                    '2\n'
                                                    'End'}}}

>>> 
>>> print (ddiff['values_changed']["root[4]['b']"]["diff"])
--- 
+++ 
@@ -1,5 +1,4 @@
-world!
-Goodbye!
+world
 1
 2
 End

Alteração de tipo

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, 3]}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":"world\n\n\nEnd"}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff, indent = 2)
{ 'type_changes': { "root[4]['b']": { 'newtype': <class 'str'>,
                                      'newvalue': 'world\n\n\nEnd',
                                      'oldtype': <class 'list'>,
                                      'oldvalue': [1, 2, 3]}}}

Diferença de lista

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, 3, 4]}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2]}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff, indent = 2)
{'iterable_item_removed': {"root[4]['b'][2]": 3, "root[4]['b'][3]": 4}}

Diferença de lista 2:

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, 3]}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 3, 2, 3]}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff, indent = 2)
{ 'iterable_item_added': {"root[4]['b'][3]": 3},
  'values_changed': { "root[4]['b'][1]": {'newvalue': 3, 'oldvalue': 2},
                      "root[4]['b'][2]": {'newvalue': 2, 'oldvalue': 3}}}

Listar a diferença de ordem de ignição ou duplicatas: (com os mesmos dicionários acima)

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, 3]}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 3, 2, 3]}}
>>> ddiff = DeepDiff(t1, t2, ignore_order=True)
>>> print (ddiff)
{}

Lista que contém o dicionário:

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, {1:1, 2:2}]}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, {1:3}]}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff, indent = 2)
{ 'dic_item_removed': ["root[4]['b'][2][2]"],
  'values_changed': {"root[4]['b'][2][1]": {'newvalue': 3, 'oldvalue': 1}}}

Conjuntos:

>>> t1 = {1, 2, 8}
>>> t2 = {1, 2, 3, 5}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (DeepDiff(t1, t2))
{'set_item_added': ['root[3]', 'root[5]'], 'set_item_removed': ['root[8]']}

Tuplas nomeadas:

>>> from collections import namedtuple
>>> Point = namedtuple('Point', ['x', 'y'])
>>> t1 = Point(x=11, y=22)
>>> t2 = Point(x=11, y=23)
>>> pprint (DeepDiff(t1, t2))
{'values_changed': {'root.y': {'newvalue': 23, 'oldvalue': 22}}}

Objetos personalizados:

>>> class ClassA(object):
...     a = 1
...     def __init__(self, b):
...         self.b = b
... 
>>> t1 = ClassA(1)
>>> t2 = ClassA(2)
>>> 
>>> pprint(DeepDiff(t1, t2))
{'values_changed': {'root.b': {'newvalue': 2, 'oldvalue': 1}}}

Atributo de objeto adicionado:

>>> t2.c = "new attribute"
>>> pprint(DeepDiff(t1, t2))
{'attribute_added': ['root.c'],
 'values_changed': {'root.b': {'newvalue': 2, 'oldvalue': 1}}}
Seperman
fonte
20

Pode ser feito usando o operador python XOR.

  • Isso removerá as duplicatas em cada lista
  • Isso mostrará a diferença de temp1 de temp2 e temp2 de temp1.

set(temp1) ^ set(temp2)
Super Nova
fonte
funciona, mas por que?
ZakS 17/02
a melhor resposta!
Artsiom Praneuski
que resposta! tão pitonico !!!! amazing
toing_toing
18

maneira mais simples,

use set (). diferença (set ())

list_a = [1,2,3]
list_b = [2,3]
print set(list_a).difference(set(list_b))

a resposta é set([1])

pode imprimir como uma lista,

print list(set(list_a).difference(set(list_b)))
Mohideen bin Mohammed
fonte
14

Se você está realmente olhando para o desempenho, use numpy!

Aqui está o caderno completo como uma essência no github com comparação entre list, numpy e pandas.

https://gist.github.com/denfromufa/2821ff59b02e9482be15d27f2bbd4451

insira a descrição da imagem aqui

denfromufa
fonte
Eu atualizei o notebook no link e também na captura de tela. Surpreendentemente, os pandas são mais lentos que entorpecidos, mesmo ao mudar para hashtable internamente. Em parte, isso pode ser devido ao upcasting para int64.
Denfromufa
13

eu irei falar, já que nenhuma das soluções presentes produz uma tupla:

temp3 = tuple(set(temp1) - set(temp2))

alternativamente:

#edited using @Mark Byers idea. If you accept this one as answer, just accept his instead.
temp3 = tuple(x for x in temp1 if x not in set(temp2))

Como as outras respostas que não são da tupla, nessa direção, ele preserva a ordem

aaronasterling
fonte
11

Eu queria algo que levaria duas listas e poderia fazer o que diffnos bashfaz. Como essa pergunta aparece primeiro quando você pesquisa "python diff two lists" e não é muito específica, vou postar o que foi apresentado.

Usando SequenceMatherfrom difflibvocê pode comparar duas listas como difffaz. Nenhuma das outras respostas lhe dirá a posição em que a diferença ocorre, mas essa sim. Algumas respostas dão a diferença em apenas uma direção. Alguns reordenam os elementos. Alguns não lidam com duplicatas. Mas esta solução oferece uma verdadeira diferença entre duas listas:

a = 'A quick fox jumps the lazy dog'.split()
b = 'A quick brown mouse jumps over the dog'.split()

from difflib import SequenceMatcher

for tag, i, j, k, l in SequenceMatcher(None, a, b).get_opcodes():
  if tag == 'equal': print('both have', a[i:j])
  if tag in ('delete', 'replace'): print('  1st has', a[i:j])
  if tag in ('insert', 'replace'): print('  2nd has', b[k:l])

Isso gera:

both have ['A', 'quick']
  1st has ['fox']
  2nd has ['brown', 'mouse']
both have ['jumps']
  2nd has ['over']
both have ['the']
  1st has ['lazy']
both have ['dog']

Obviamente, se seu aplicativo fizer as mesmas suposições que as outras respostas, você se beneficiará mais delas. Mas se você estiver procurando por uma verdadeiradiff funcionalidade , esse é o único caminho a percorrer.

Por exemplo, nenhuma das outras respostas poderia lidar com:

a = [1,2,3,4,5]
b = [5,4,3,2,1]

Mas este faz:

  2nd has [5, 4, 3, 2]
both have [1]
  1st has [2, 3, 4, 5]
arekolek
fonte
10

Tente o seguinte:

temp3 = set(temp1) - set(temp2)
Maciej Kucharz
fonte
10

isso pode ser ainda mais rápido do que a compreensão da lista de Mark:

list(itertools.filterfalse(set(temp2).__contains__, temp1))
Mohammed
fonte
7
Pode querer incluir a parte from itertools import filterfalseaqui. Observe também que isso não retorna uma sequência como as outras, mas retorna um iterador.
precisa saber é o seguinte
7

Aqui está uma Counterresposta para o caso mais simples.

Isso é mais curto do que o descrito acima, que difere nos dois sentidos, porque ele faz exatamente o que a pergunta faz: gerar uma lista do que está na primeira lista, mas não na segunda.

from collections import Counter

lst1 = ['One', 'Two', 'Three', 'Four']
lst2 = ['One', 'Two']

c1 = Counter(lst1)
c2 = Counter(lst2)
diff = list((c1 - c2).elements())

Como alternativa, dependendo das suas preferências de legibilidade, cria uma linha decente decente:

diff = list((Counter(lst1) - Counter(lst2)).elements())

Resultado:

['Three', 'Four']

Observe que você pode remover a list(...)chamada se estiver apenas repetindo.

Como esta solução usa contadores, ela lida com quantidades adequadamente versus as muitas respostas baseadas em conjuntos. Por exemplo nesta entrada:

lst1 = ['One', 'Two', 'Two', 'Two', 'Three', 'Three', 'Four']
lst2 = ['One', 'Two']

A saída é:

['Two', 'Two', 'Three', 'Three', 'Four']
Taylor Edmiston
fonte
5

Você poderia usar um método ingênuo se os elementos da lista de distribuição forem classificados e configurados.

list1=[1,2,3,4,5]
list2=[1,2,3]

print list1[len(list2):]

ou com métodos de conjunto nativo:

subset=set(list1).difference(list2)

print subset

import timeit
init = 'temp1 = list(range(100)); temp2 = [i * 2 for i in range(50)]'
print "Naive solution: ", timeit.timeit('temp1[len(temp2):]', init, number = 100000)
print "Native set solution: ", timeit.timeit('set(temp1).difference(temp2)', init, number = 100000)

Solução ingênua: 0.0787101593292

Solução do conjunto nativo: 0.998837615564

soundcorner
fonte
5

Estou muito atrasado no jogo para isso, mas você pode fazer uma comparação do desempenho de alguns dos códigos mencionados acima com isso, dois dos concorrentes mais rápidos são:

list(set(x).symmetric_difference(set(y)))
list(set(x) ^ set(y))

Peço desculpas pelo nível elementar de codificação.

import time
import random
from itertools import filterfalse

# 1 - performance (time taken)
# 2 - correctness (answer - 1,4,5,6)
# set performance
performance = 1
numberoftests = 7

def answer(x,y,z):
    if z == 0:
        start = time.clock()
        lists = (str(list(set(x)-set(y))+list(set(y)-set(y))))
        times = ("1 = " + str(time.clock() - start))
        return (lists,times)

    elif z == 1:
        start = time.clock()
        lists = (str(list(set(x).symmetric_difference(set(y)))))
        times = ("2 = " + str(time.clock() - start))
        return (lists,times)

    elif z == 2:
        start = time.clock()
        lists = (str(list(set(x) ^ set(y))))
        times = ("3 = " + str(time.clock() - start))
        return (lists,times)

    elif z == 3:
        start = time.clock()
        lists = (filterfalse(set(y).__contains__, x))
        times = ("4 = " + str(time.clock() - start))
        return (lists,times)

    elif z == 4:
        start = time.clock()
        lists = (tuple(set(x) - set(y)))
        times = ("5 = " + str(time.clock() - start))
        return (lists,times)

    elif z == 5:
        start = time.clock()
        lists = ([tt for tt in x if tt not in y])
        times = ("6 = " + str(time.clock() - start))
        return (lists,times)

    else:    
        start = time.clock()
        Xarray = [iDa for iDa in x if iDa not in y]
        Yarray = [iDb for iDb in y if iDb not in x]
        lists = (str(Xarray + Yarray))
        times = ("7 = " + str(time.clock() - start))
        return (lists,times)

n = numberoftests

if performance == 2:
    a = [1,2,3,4,5]
    b = [3,2,6]
    for c in range(0,n):
        d = answer(a,b,c)
        print(d[0])

elif performance == 1:
    for tests in range(0,10):
        print("Test Number" + str(tests + 1))
        a = random.sample(range(1, 900000), 9999)
        b = random.sample(range(1, 900000), 9999)
        for c in range(0,n):
            #if c not in (1,4,5,6):
            d = answer(a,b,c)
            print(d[1])
Alex Jacob
fonte
5

Aqui estão alguns exemplos simples de preservação de pedidos maneiras de diferenciar duas listas de strings.

Código

Uma abordagem incomum usando pathlib:

import pathlib


temp1 = ["One", "Two", "Three", "Four"]
temp2 = ["One", "Two"]

p = pathlib.Path(*temp1)
r = p.relative_to(*temp2)
list(r.parts)
# ['Three', 'Four']

Isso pressupõe que ambas as listas contêm seqüências de caracteres com começos equivalentes. Veja os documentos para mais detalhes. Observe que não é particularmente rápido se comparado às operações definidas.


Uma implementação direta usando itertools.zip_longest:

import itertools as it


[x for x, y in it.zip_longest(temp1, temp2) if x != y]
# ['Three', 'Four']
pylang
fonte
1
A solução itertools funciona apenas quando os elementos estão alinhados temp1e temp2alinhados. Se, por exemplo, você inverter os elementos temp2ou inserir algum outro valor no início de temp2, o listcomp retornará os mesmos elementos que emtemp1
KenHBS
Sim, é uma característica dessas abordagens. Como mencionado, essas soluções preservam a ordem - elas assumem alguma ordem relativa entre as listas. Uma solução não ordenada seria diferenciar dois conjuntos.
Pylang
4

Esta é outra solução:

def diff(a, b):
    xa = [i for i in set(a) if i not in b]
    xb = [i for i in set(b) if i not in a]
    return xa + xb
manhgd
fonte
4

Se você se deparar, TypeError: unhashable type: 'list'precisará transformar listas ou conjuntos em tuplas, por exemplo

set(map(tuple, list_of_lists1)).symmetric_difference(set(map(tuple, list_of_lists2)))

Veja também Como comparar uma lista de listas / conjuntos em python?

kqw
fonte
4

Digamos que temos duas listas

list1 = [1, 3, 5, 7, 9]
list2 = [1, 2, 3, 4, 5]

podemos ver nas duas listas acima que os itens 1, 3, 5 existem na lista2 e os itens 7, 9 não. Por outro lado, os itens 1, 3, 5 existem na lista1 e os itens 2, 4 não.

Qual é a melhor solução para retornar uma nova lista contendo os itens 7, 9 e 2, 4?

Todas as respostas acima encontram a solução, agora qual é a melhor opção?

def difference(list1, list2):
    new_list = []
    for i in list1:
        if i not in list2:
            new_list.append(i)

    for j in list2:
        if j not in list1:
            new_list.append(j)
    return new_list

versus

def sym_diff(list1, list2):
    return list(set(list1).symmetric_difference(set(list2)))

Usando timeit, podemos ver os resultados

t1 = timeit.Timer("difference(list1, list2)", "from __main__ import difference, 
list1, list2")
t2 = timeit.Timer("sym_diff(list1, list2)", "from __main__ import sym_diff, 
list1, list2")

print('Using two for loops', t1.timeit(number=100000), 'Milliseconds')
print('Using two for loops', t2.timeit(number=100000), 'Milliseconds')

retorna

[7, 9, 2, 4]
Using two for loops 0.11572412995155901 Milliseconds
Using symmetric_difference 0.11285737506113946 Milliseconds

Process finished with exit code 0
Carson
fonte
3

versão de linha única da solução arulmr

def diff(listA, listB):
    return set(listA) - set(listB) | set(listA) -set(listB)
sreemanth pulagam
fonte
3

se você quiser algo mais como um changeset ... poderia usar o Counter

from collections import Counter

def diff(a, b):
  """ more verbose than needs to be, for clarity """
  ca, cb = Counter(a), Counter(b)
  to_add = cb - ca
  to_remove = ca - cb
  changes = Counter(to_add)
  changes.subtract(to_remove)
  return changes

lista = ['one', 'three', 'four', 'four', 'one']
listb = ['one', 'two', 'three']

In [127]: diff(lista, listb)
Out[127]: Counter({'two': 1, 'one': -1, 'four': -2})
# in order to go from lista to list b, you need to add a "two", remove a "one", and remove two "four"s

In [128]: diff(listb, lista)
Out[128]: Counter({'four': 2, 'one': 1, 'two': -1})
# in order to go from listb to lista, you must add two "four"s, add a "one", and remove a "two"
Nick Franceschina
fonte
2

Podemos calcular a interseção menos a união de listas:

temp1 = ['One', 'Two', 'Three', 'Four']
temp2 = ['One', 'Two', 'Five']

set(temp1+temp2)-(set(temp1)&set(temp2))

Out: set(['Four', 'Five', 'Three']) 
Mohammad Etemaddar
fonte
2

Isso pode ser resolvido com uma linha. A pergunta é dada duas listas (temp1 e temp2) retornam sua diferença em uma terceira lista (temp3).

temp3 = list(set(temp1).difference(set(temp2)))
fgaim
fonte
1

Aqui está uma maneira simples de distinguir duas listas (qualquer que seja o conteúdo), você pode obter o resultado conforme mostrado abaixo:

>>> from sets import Set
>>>
>>> l1 = ['xvda', False, 'xvdbb', 12, 'xvdbc']
>>> l2 = ['xvda', 'xvdbb', 'xvdbc', 'xvdbd', None]
>>>
>>> Set(l1).symmetric_difference(Set(l2))
Set([False, 'xvdbd', None, 12])

Espero que isso seja útil.

SK Venkat
fonte
0

Eu prefiro usar a conversão para conjuntos e, em seguida, usando a função "diferença ()". O código completo é:

temp1 = ['One', 'Two', 'Three', 'Four'  ]                   
temp2 = ['One', 'Two']
set1 = set(temp1)
set2 = set(temp2)
set3 = set1.difference(set2)
temp3 = list(set3)
print(temp3)

Resultado:

>>>print(temp3)
['Three', 'Four']

É o mais fácil de entender e, no futuro, se você trabalhar com dados grandes, convertê-los em conjuntos removerá duplicatas, caso não sejam necessárias. Espero que ajude ;-)

Shakhyar Gogoi
fonte
-1
(list(set(a)-set(b))+list(set(b)-set(a)))
nadhem
fonte
3
Além de fornecer a resposta, você pode dar uma explicação de como ela funciona / se aplica a esse problema específico? Respostas e soluções são ótimas, mas guias e explicações detalhadas são infinitamente melhores.
Busse
-1
def diffList(list1, list2):     # returns the difference between two lists.
    if len(list1) > len(list2):
        return (list(set(list1) - set(list2)))
    else:
        return (list(set(list2) - set(list1)))

por exemplo, se list1 = [10, 15, 20, 25, 30, 35, 40]e list2 = [25, 40, 35]então a lista retornada seráoutput = [10, 20, 30, 15]

csg
fonte
Você não pode fazer isso para operações com diferenças. Mesmo no caso de números inteiros, se você disser a uma função para executar 'a - b', ela deve subtrair 'b' de 'a' apenas, não importa se 'b' for maior que 'a' ou não. Semelhante é o caso da lista e dos conjuntos. A - B e B - A podem ser operações válidas, independentemente dos comprimentos de A e B, basta excluir o conteúdo de B de A para executar A - B.
Abu Talha Danish