Obtenez la différence entre deux listes

812

J'ai deux listes en Python, comme celles-ci:

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

J'ai besoin de créer une troisième liste avec des éléments de la première liste qui ne sont pas présents dans la seconde. De l'exemple, je dois obtenir:

temp3 = ['Three', 'Four']

Existe-t-il des moyens rapides sans cycles et sans vérification?

Max Frai
la source
14
Les éléments sont-ils garantis uniques? Si vous avez temp1 = ['One', 'One', 'One']et temp2 = ['One']voulez-vous ['One', 'One']revenir, ou []?
Michael Mrozek
@ michael-mrozek ils sont uniques.
Max Frai
12
Voulez-vous conserver l'ordre des éléments?
Mark Byers

Réponses:

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

Attention à ça

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

où vous pourriez vous attendre / vouloir l'égaler set([1, 3]). Si vous voulez set([1, 3])comme réponse, vous devrez utiliser set([1, 2]).symmetric_difference(set([2, 3])).

ars
la source
27
@Drewdin: Les listes ne prennent pas en charge l'opérande "-". Les ensembles, cependant, font, et c'est ce qui est démontré ci-dessus si vous regardez de près.
Godsmith
1
merci, j'ai fini par utiliser set (ListA) .symmetric_difference (ListB)
Drewdin
43
la différence symétrique peut être écrite avec: ^ (set1 ^ set2)
Bastian
10
S'il vous plaît, pourriez-vous modifier votre réponse et souligner que cela ne renvoie que temp1-temp2? .. Comme d'autres l'ont dit, pour retourner toutes les différences, vous devez utiliser la différence sysmétrique: list (set (temp1) ^ set (temp2))
rkachach
Pourquoi est-ce que j'obtiens TypeError: 'str' object is not callablequand a = [1,2,2,2,3]b = [2]
j'exécute
478

Les solutions existantes proposent toutes l'une ou l'autre:

  • Plus rapide que les performances O (n * m).
  • Conserver l'ordre de la liste d'entrée.

Mais jusqu'à présent, aucune solution n'a les deux. Si vous voulez les deux, essayez ceci:

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

Test 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)

Résultats:

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

La méthode que j'ai présentée ainsi que la préservation de l'ordre est également (légèrement) plus rapide que la soustraction d'ensemble car elle ne nécessite pas la construction d'un ensemble inutile. La différence de performances serait plus notable si la première liste est considérablement plus longue que la seconde et si le hachage est coûteux. Voici un deuxième test qui le démontre:

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

Résultats:

11.3836875916 # ars' answer
3.63890368748 # this answer (3 times faster!)
37.7445402279 # matt b's answer
Mark Byers
la source
2
Prise en charge supplémentaire de cette réponse: parcouru un cas d'utilisation où la préservation de l'ordre des listes était importante pour les performances. Lorsque je travaillais avec des objets tarinfo ou zipinfo, j'utilisais la soustraction d'ensemble. Pour exclure certains objets tarinfo d'être extraits de l'archive. La création de la nouvelle liste a été rapide mais super lente lors de l'extraction. La raison m'a d'abord éludé. Il s'avère que la réorganisation de la liste des objets tarinfo a causé une énorme pénalité de performance. Le passage à la méthode de compréhension de liste a sauvé la journée.
Ray Thompson
@MarkByers - je devrais peut-être écrire une toute nouvelle question à ce sujet. Mais comment cela fonctionnerait-il en boucle? Par exemple, si mes temp1 et temp2 continuent de changer .. et que je veux ajouter les nouvelles informations à temp3?
Ason
@MarkByers - sonne bien. Je vais continuer à y penser un peu. mais +1 pour une excellente solution.
Ason
Je suis d'accord avec @Dejel >>> temp1 = ['One', 'Two', 'Three', 'Four'] >>> temp2 = ['One', 'Two', 'Six'] >>> s = set (temp2) >>> temp3 = [x pour x dans temp1 si x pas dans s] >>> temp3 ['Three', 'Four']
earlonrails
3
@haccks Parce que la vérification de l'appartenance à une liste est une opération O (n) (itération sur toute la liste), mais la vérification de l'appartenance à un ensemble est O (1).
Mark Byers
86
temp3 = [item for item in temp1 if item not in temp2]
mat b
la source
15
Devenir temp2un ensemble avant rendrait cela un peu plus efficace.
lunaryorn
3
Vrai, cela dépend si Ockonal se soucie des doublons ou non (la question d'origine ne dit pas)
mat b
2
Le commentaire dit que les (listes | tuples) n'ont pas de doublons.
1
J'ai voté pour votre réponse parce que je pensais que vous aviez raison au sujet des doublons au début. Mais item not in temp2et item not in set(temp2)renverra toujours les mêmes résultats, qu'il y ait des doublons ou non temp2.
arekolek
5
Votez pour ne pas exiger que les éléments de la liste soient lavables.
Brent
23

La différence entre deux listes (disons liste1 et liste2) peut être trouvée en utilisant la fonction simple suivante.

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))

En utilisant la fonction ci-dessus, la différence peut être trouvée en utilisant diff(temp2, temp1)ou diff(temp1, temp2). Les deux donneront le résultat ['Four', 'Three']. Vous n'avez pas à vous soucier de l'ordre de la liste ou de la liste à donner en premier.

Référence doc Python

arulmr
la source
7
Pourquoi ne pas définir (list1) .symmetric_difference (set (list2))?
swietyy
20

Dans le cas où vous voulez la différence récursivement, j'ai écrit un package pour python: https://github.com/seperman/deepdiff

Installation

Installer depuis PyPi:

pip install deepdiff

Exemple d'utilisation

Importation

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

Le même objet revient vide

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

Le type d'un élément a changé

>>> 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}}}

La valeur d'un article a changé

>>> 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}}}

Élément ajouté et / ou supprimé

>>> 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}}}

Différence de chaîne

>>> 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'}}}

Différence de chaîne 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

Changement de type

>>> 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]}}}

Liste des différences

>>> 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}}

Énumérez la différence 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}}}

Liste des différences en ignorant l'ordre ou les doublons: (avec les mêmes dictionnaires que ci-dessus)

>>> 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)
{}

Liste contenant le dictionnaire:

>>> 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}}}

Ensembles:

>>> 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]']}

Tuples nommés:

>>> 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}}}

Objets personnalisés:

>>> 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}}}

Attribut d'objet ajouté:

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

Peut être fait en utilisant l'opérateur XOR python.

  • Cela supprimera les doublons dans chaque liste
  • Cela montrera la différence de temp1 de temp2 et temp2 de temp1.

set(temp1) ^ set(temp2)
SuperNova
la source
fonctionne, mais pourquoi?
ZakS
la meilleure réponse!
Artsiom Praneuski
quelle réponse! si pythonique !!!! incroyable
toing_toing
18

moyen le plus simple,

utilisez set (). difference (set ())

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

la réponse est set([1])

peut imprimer sous forme de liste,

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

Si vous êtes vraiment à la recherche de performances, utilisez numpy!

Voici le carnet complet en tant qu'essentiel sur github avec comparaison entre liste, numpy et pandas.

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

entrez la description de l'image ici

denfromufa
la source
j'ai mis à jour le cahier dans le lien et aussi la capture d'écran. Étonnamment, les pandas sont plus lents que numpy même lors du passage à la table de hachage en interne. Cela peut être dû en partie à la conversion vers l'int64.
denfromufa
13

je vais lancer car aucune des solutions actuelles ne donne un tuple:

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

alternativement:

#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))

Comme les autres non-tuple donnant des réponses dans ce sens, il préserve l'ordre

aaronasterling
la source
11

Je voulais quelque chose qui prendrait deux listes et pourrait faire quoi diffenbash fait. Puisque cette question apparaît en premier lorsque vous recherchez "python diff two lists" et n'est pas très spécifique, je posterai ce que j'ai trouvé.

À l'aide SequenceMatherde, difflibvous pouvez comparer deux listes comme le difffait. Aucune des autres réponses ne vous indiquera la position où la différence se produit, mais celle-ci le fait. Certaines réponses donnent la différence dans une seule direction. Certains réorganisent les éléments. Certains ne gèrent pas les doublons. Mais cette solution vous donne une vraie différence entre deux listes:

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])

Cela produit:

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']

Bien sûr, si votre application fait les mêmes hypothèses que les autres réponses, vous en profiterez le plus. Mais si vous cherchez un vraidiff fonctionnalité, c'est la seule façon de procéder.

Par exemple, aucune des autres réponses n'a pu gérer:

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

Mais celui-ci fait:

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

Essaye ça:

temp3 = set(temp1) - set(temp2)
Maciej Kucharz
la source
10

cela pourrait être encore plus rapide que la compréhension de la liste de Mark:

list(itertools.filterfalse(set(temp2).__contains__, temp1))
Mohammed
la source
7
Pourrait vouloir inclure le from itertools import filterfalsebit ici. Notez également que cela ne renvoie pas une séquence comme les autres, il renvoie un itérateur.
Matt Luongo
7

Voici une Counterréponse pour le cas le plus simple.

C'est plus court que celui ci-dessus qui fait des différences bidirectionnelles car il ne fait que ce que la question demande: générer une liste de ce qui est dans la première liste mais pas la seconde.

from collections import Counter

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

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

Alternativement, en fonction de vos préférences de lisibilité, il en résulte une doublure décente:

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

Production:

['Three', 'Four']

Notez que vous pouvez supprimer le list(...) appel si vous êtes en train de le parcourir.

Étant donné que cette solution utilise des compteurs, elle gère correctement les quantités par rapport aux nombreuses réponses basées sur des ensembles. Par exemple sur cette entrée:

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

La sortie est:

['Two', 'Two', 'Three', 'Three', 'Four']
Taylor Edmiston
la source
5

Vous pouvez utiliser une méthode naïve si les éléments de la liste de diffusion sont triés et définis.

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

print list1[len(list2):]

ou avec des méthodes de jeu natives:

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)

Solution naïve: 0,0787101593292

Solution de jeu natif: 0.998837615564

soundcorner
la source
5

Je suis un peu trop tard dans le jeu pour cela, mais vous pouvez comparer les performances de certains des codes susmentionnés avec cela, deux des prétendants les plus rapides sont,

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

Je m'excuse pour le niveau élémentaire de codage.

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
la source
5

Voici quelques simples, qui préservent l'ordre des moyens de diffing deux listes de chaînes.

Code

Une approche inhabituelle utilisant 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']

Cela suppose que les deux listes contiennent des chaînes avec des débuts équivalents. Voir les documents pour plus de détails. Remarque, il n'est pas particulièrement rapide par rapport aux opérations définies.


Une implémentation simple utilisant itertools.zip_longest:

import itertools as it


[x for x, y in it.zip_longest(temp1, temp2) if x != y]
# ['Three', 'Four']
pylang
la source
1
La solution itertools ne fonctionne que lorsque les éléments sont bien alignés temp1et temp2alignés. Si vous, par exemple, retournez les éléments dans temp2ou insérez une autre valeur au début de temp2, le listcomp renverra simplement les mêmes éléments que danstemp1
KenHBS
Oui, c'est une caractéristique de ces approches. Comme mentionné, ces solutions préservent l'ordre - elles supposent un certain ordre relatif entre les listes. Une solution non ordonnée serait de différencier deux ensembles.
pylang
4

Voici une autre solution:

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
la source
4

Si vous rencontrez, TypeError: unhashable type: 'list'vous devez transformer des listes ou des ensembles en tuples, par exemple

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

Voir aussi Comment comparer une liste de listes / ensembles en python?

kqw
la source
4

Disons que nous avons deux listes

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

nous pouvons voir à partir des deux listes ci-dessus que les éléments 1, 3, 5 existent dans la liste 2 et les éléments 7, 9 n'existent pas. En revanche, les éléments 1, 3, 5 existent dans la liste 1 et les éléments 2, 4 n'existent pas.

Quelle est la meilleure solution pour renvoyer une nouvelle liste contenant les éléments 7, 9 et 2, 4?

Toutes les réponses ci-dessus trouvent la solution, quelle est maintenant la plus optimale?

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

contre

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

En utilisant le temps, nous pouvons voir les résultats

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')

Retour

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

Process finished with exit code 0
Carson
la source
3

version monoligne de la solution arulmr

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

si vous voulez quelque chose de plus comme un changeset ... pourrait utiliser 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
la source
2

Nous pouvons calculer l'intersection moins l'union des listes:

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

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

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

Cela peut être résolu avec une seule ligne. La question est donnée deux listes (temp1 et temp2) renvoient leur différence dans une troisième liste (temp3).

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

Voici un moyen simple de distinguer deux listes (quel que soit le contenu), vous pouvez obtenir le résultat comme indiqué ci-dessous:

>>> 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])

J'espère que cela vous sera utile.

SK Venkat
la source
0

Je préfère utiliser la conversion en ensembles puis utiliser la fonction "difference ()". Le code complet est:

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

Production:

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

C'est le plus facile à comprendre, et plus à l'avenir si vous travaillez avec des données volumineuses, la conversion en ensembles supprimera les doublons si les doublons ne sont pas nécessaires. J'espère que cela aide ;-)

Shakhyar Gogoi
la source
-1
(list(set(a)-set(b))+list(set(b)-set(a)))
Nadhem
la source
3
En plus de fournir la réponse, pouvez-vous expliquer comment cela fonctionne / s'applique à ce problème particulier? Les réponses et les solutions sont excellentes, mais les guides et explications détaillés sont infiniment meilleurs.
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)))

par exemple si list1 = [10, 15, 20, 25, 30, 35, 40]et list2 = [25, 40, 35]puis la liste retournée seraoutput = [10, 20, 30, 15]

csg
la source
Vous ne pouvez pas faire comme ça pour un fonctionnement différent. Même dans le cas d'entiers, si vous dites à une fonction d'exécuter «a - b», elle est censée soustraire «b» de «a» uniquement, peu importe si «b» est plus grand que «a» ou autrement. Il en va de même pour la liste et les ensembles. A - B et B - A les deux peuvent être des opérations valides quelles que soient les longueurs de A et B, il vous suffit d'exclure le contenu de B de A pour effectuer A - B.
Abu Talha Danois