Dapatkan perbedaan antara dua daftar

811

Saya memiliki dua daftar dengan Python, seperti ini:

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

Saya perlu membuat daftar ketiga dengan item dari daftar pertama yang tidak ada di daftar kedua. Dari contoh saya harus mendapatkan:

temp3 = ['Three', 'Four']

Apakah ada cara cepat tanpa siklus dan pemeriksaan?

Max Frai
sumber
14
Apakah elemen dijamin unik? Jika Anda memiliki temp1 = ['One', 'One', 'One']dan temp2 = ['One'], apakah Anda ingin ['One', 'One']kembali, atau []?
Michael Mrozek
@ michael-mrozek mereka unik.
Max Frai
12
Apakah Anda ingin mempertahankan urutan elemen?
Mark Byers

Jawaban:

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

Waspadalah itu

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

di mana Anda mungkin mengharapkan / menginginkannya sama set([1, 3]). Jika Anda ingin set([1, 3])sebagai jawaban, Anda harus menggunakannya set([1, 2]).symmetric_difference(set([2, 3])).

ars
sumber
27
@Drewdin: Daftar tidak mendukung operan "-". Set, bagaimanapun, lakukan, dan apa yang ditunjukkan di atas jika Anda melihat dari dekat.
Godsmith
1
terima kasih, saya akhirnya menggunakan set (ListA) .symmetric_difference (ListB)
Drewdin
43
perbedaan simetris dapat ditulis dengan: ^ (set1 ^ set2)
Bastian
10
Tolong, bisakah Anda mengedit jawaban Anda dan menunjukkan bahwa ini hanya mengembalikan temp1-temp2? .. Seperti yang lain katakan untuk mengembalikan semua perbedaan Anda harus menggunakan perbedaan sysmetric: list (set (temp1) ^ set (temp2))
rkachach
Mengapa saya dapat TypeError: 'str' object is not callableketika saya melakukan operasi ini a = [1,2,2,2,3]danb = [2]
d8aninja
478

Semua solusi yang ada menawarkan salah satu dari yang berikut:

  • Kinerja lebih cepat dari O (n * m).
  • Pertahankan urutan daftar input.

Namun sejauh ini tidak ada solusi yang memiliki keduanya. Jika Anda ingin keduanya, coba ini:

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

Uji kinerja

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)

Hasil:

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

Metode yang saya sajikan serta menjaga pesanan juga (sedikit) lebih cepat dari pengurangan yang ditetapkan karena tidak memerlukan konstruksi dari set yang tidak perlu. Perbedaan kinerja akan lebih terlihat jika daftar pertama jauh lebih lama daripada yang kedua dan jika hashing mahal. Inilah tes kedua yang menunjukkan ini:

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

Hasil:

11.3836875916 # ars' answer
3.63890368748 # this answer (3 times faster!)
37.7445402279 # matt b's answer
Mark Byers
sumber
2
Dukungan tambahan untuk jawaban ini: Berlari melintasi use case di mana menjaga urutan daftar penting untuk kinerja. Ketika bekerja dengan objek tarinfo atau zipinfo saya menggunakan set pengurangan. Untuk mengecualikan objek tarinfo tertentu agar tidak diekstraksi dari arsip. Membuat daftar baru itu cepat tetapi sangat lambat selama ekstraksi. Alasannya pada awalnya menghindari saya. Ternyata pemesanan ulang daftar objek tarinfo menyebabkan penalti performa yang sangat besar. Beralih ke metode pemahaman daftar menyelamatkan hari.
Ray Thompson
@ MarkByers - mungkin saya harus menulis pertanyaan yang sama sekali baru untuk ini. Tetapi bagaimana ini akan bekerja di bawah? Misalnya, apakah temp1 dan temp2 saya terus berubah .. dan saya ingin menambahkan informasi baru ke temp3?
Ason
@MarkByers - kedengarannya bagus. Saya akan terus memikirkannya sebentar. tetapi memberi +1 untuk solusi hebat.
Ason
Saya setuju dengan @Dejel >>> temp1 = ['One', 'Two', 'Three', 'Four'] >>> temp2 = ['One', 'Two', 'Six'] >>> s = set (temp2) >>> temp3 = [x untuk x dalam temp1 jika x tidak dalam] >>> temp3 ['Tiga', 'Empat']
earlonrails
3
@haccks Karena memeriksa keanggotaan daftar adalah operasi O (n) (mengulangi seluruh daftar), tetapi memeriksa keanggotaan set adalah O (1).
Mark Byers
86
temp3 = [item for item in temp1 if item not in temp2]
matt b
sumber
15
Mengubah temp2menjadi himpunan sebelumnya akan membuat ini sedikit lebih efisien.
lunaryorn
3
Benar, tergantung apakah Ockonal peduli dengan duplikat atau tidak (pertanyaan awal tidak mengatakan)
matt b
2
Komentar mengatakan (daftar | tupel) tidak memiliki duplikat.
1
Saya mengubah jawaban Anda karena saya pikir Anda benar tentang duplikat pada awalnya. Tetapi item not in temp2dan item not in set(temp2)akan selalu mengembalikan hasil yang sama, terlepas dari apakah ada duplikat atau tidak temp2.
arekolek
5
Pilih untuk tidak membutuhkan item daftar untuk dapat di hashable.
Brent
23

Perbedaan antara dua daftar (katakanlah list1 dan list2) dapat ditemukan menggunakan fungsi sederhana berikut.

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)

atau

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

Dengan Menggunakan fungsi di atas, perbedaan dapat ditemukan menggunakan diff(temp2, temp1)atau diff(temp1, temp2). Keduanya akan memberikan hasilnya ['Four', 'Three']. Anda tidak perlu khawatir tentang urutan daftar atau daftar mana yang harus diberikan terlebih dahulu.

Referensi dokumen Python

arulmr
sumber
7
Mengapa tidak mengatur (list1) .symmetric_difference (set (list2))?
swietyy
20

Jika Anda menginginkan perbedaan secara rekursif, saya telah menulis paket untuk python: https://github.com/seperman/deepdiff

Instalasi

Instal dari PyPi:

pip install deepdiff

Contoh penggunaan

Pengimporan

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

Objek yang sama kembali kosong

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

Jenis item telah berubah

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

Nilai suatu barang telah berubah

>>> 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 ditambahkan dan / atau dihapus

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

Perbedaan string

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

Perbedaan string 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

Ketik perubahan

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

Daftar perbedaan

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

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

Daftar perbedaan mengabaikan urutan atau duplikat: (dengan kamus yang sama seperti di atas)

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

Daftar yang berisi kamus:

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

Set:

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

Dinamai Tuples:

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

Objek khusus:

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

Atribut objek ditambahkan:

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

Dapat dilakukan dengan menggunakan operator python XOR.

  • Ini akan menghapus duplikat di setiap daftar
  • Ini akan menunjukkan perbedaan temp1 dari temp2 dan temp2 dari temp1.

set(temp1) ^ set(temp2)
SuperNova
sumber
bekerja, tetapi mengapa?
ZakS
jawaban terbaik!
Artsiom Praneuski
jawaban yang sangat bagus! sangat pythonic !!!! amazing
toing_toing
18

cara paling sederhana,

gunakan set (). perbedaan (set ())

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

jawabannya adalah set([1])

dapat mencetak sebagai daftar,

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

Jika Anda benar-benar melihat ke kinerja, maka gunakan numpy!

Berikut ini adalah buku catatan lengkap sebagai inti pada github dengan perbandingan antara daftar, numpy, dan panda.

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

masukkan deskripsi gambar di sini

denfromufa
sumber
saya memperbarui buku catatan di tautan dan juga tangkapan layar. Panda mengejutkan lebih lambat daripada numpy bahkan ketika beralih ke hashtable secara internal. Sebagian ini mungkin karena upcasting ke int64.
denfromufa
13

saya akan melemparkan karena tidak ada solusi yang menghasilkan tuple:

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

kalau tidak:

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

Seperti jawaban non-tuple lainnya yang menghasilkan arah ini, ia menjaga ketertiban

aaronasterling
sumber
11

Aku ingin sesuatu yang akan mengambil dua daftar dan bisa melakukan apa yang diffdi bashlakukan. Karena pertanyaan ini muncul pertama kali ketika Anda mencari "python diff two list" dan tidak terlalu spesifik, saya akan memposting apa yang saya dapatkan.

Menggunakan SequenceMatherdaridifflib Anda dapat membandingkan dua daftar seperti diffhalnya. Tidak ada jawaban lain yang akan memberi tahu Anda posisi di mana perbedaan itu terjadi, tetapi jawaban ini tidak. Beberapa jawaban memberikan perbedaan hanya dalam satu arah. Beberapa menyusun ulang elemen. Beberapa tidak menangani duplikat. Tetapi solusi ini memberi Anda perbedaan nyata antara dua daftar:

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

Output ini:

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

Tentu saja, jika aplikasi Anda membuat asumsi yang sama dengan jawaban lainnya, Anda akan mendapat manfaat paling banyak dari mereka. Tetapi jika Anda mencari yang benardiff fungsionalitas yang , maka ini adalah satu-satunya cara untuk pergi.

Misalnya, tidak ada jawaban lain yang dapat menangani:

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

Tapi yang ini:

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

Coba ini:

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

ini bisa lebih cepat daripada pemahaman daftar Markus:

list(itertools.filterfalse(set(temp2).__contains__, temp1))
Mohammed
sumber
7
Mungkin ingin memasukkan from itertools import filterfalsesedikit di sini. Perhatikan juga bahwa ini tidak mengembalikan urutan seperti yang lain, itu mengembalikan iterator.
Matt Luongo
7

Inilah Counterjawaban untuk kasus paling sederhana.

Ini lebih pendek daripada yang di atas yang melakukan dua arah diffs karena hanya melakukan persis apa yang ditanyakan: menghasilkan daftar apa yang ada di daftar pertama tetapi bukan yang kedua.

from collections import Counter

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

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

Atau, tergantung pada preferensi keterbacaan Anda, itu membuat satu baris yang layak:

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

Keluaran:

['Three', 'Four']

Perhatikan bahwa Anda dapat menghapus list(...)panggilan jika Anda hanya mengulanginya.

Karena solusi ini menggunakan penghitung, ia menangani jumlah dengan benar vs banyak jawaban berbasis set. Misalnya pada input ini:

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

Outputnya adalah:

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

Anda bisa menggunakan metode naif jika elemen-elemen dari diflist diurutkan dan ditetapkan.

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

print list1[len(list2):]

atau dengan metode kumpulan asli:

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)

Solusi naif: 0,0787101593292

Solusi set asli: 0.998837615564

soundcorner
sumber
5

Saya sedikit terlambat dalam permainan untuk ini, tetapi Anda dapat melakukan perbandingan kinerja beberapa kode yang disebutkan di atas dengan ini, dua pesaing tercepat adalah,

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

Saya minta maaf untuk pengkodean tingkat dasar.

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
sumber
5

Berikut adalah beberapa cara sederhana, mempertahankan urutan untuk membedakan dua daftar string.

Kode

Pendekatan yang tidak biasa menggunakan 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']

Ini mengasumsikan kedua daftar berisi string dengan permulaan yang setara. Lihat dokumen untuk detail lebih lanjut. Catatan, ini tidak terlalu cepat dibandingkan dengan operasi yang ditetapkan.


Implementasi langsung menggunakan itertools.zip_longest:

import itertools as it


[x for x, y in it.zip_longest(temp1, temp2) if x != y]
# ['Three', 'Four']
pylang
sumber
1
Solusi itertools hanya berfungsi ketika elemen-elemen masuk temp1dan temp2berbaris dengan baik. Jika Anda, misalnya, membalikkan elemen temp2atau memasukkan nilai lain di awal temp2, listcomp hanya akan mengembalikan elemen yang sama seperti ditemp1
KenHBS
Ya, ini adalah fitur dari pendekatan ini. Seperti yang disebutkan, solusi ini menjaga pesanan - mereka menganggap beberapa urutan relatif antara daftar. Solusi unordered adalah untuk membedakan dua set.
pylang
4

Ini adalah solusi lain:

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
sumber
4

Jika Anda bertemu TypeError: unhashable type: 'list'Anda perlu mengubah daftar atau set menjadi tupel, mis

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

Lihat juga Bagaimana membandingkan daftar daftar / set dengan python?

kqw
sumber
4

Katakanlah kita memiliki dua daftar

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

kita dapat melihat dari dua daftar di atas bahwa item 1, 3, 5 ada di list2 dan item 7, 9 tidak. Di sisi lain, item 1, 3, 5 ada di list1 dan item 2, 4 tidak.

Apa solusi terbaik untuk mengembalikan daftar baru yang berisi item 7, 9 dan 2, 4?

Semua jawaban di atas menemukan solusinya, sekarang apa yang paling optimal?

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

melawan

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

Menggunakan timeit kita bisa melihat hasilnya

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

kembali

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

Process finished with exit code 0
Carson
sumber
3

versi baris tunggal dari solusi arulmr

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

jika Anda menginginkan sesuatu yang lebih seperti setelan perubahan ... bisa menggunakan Penghitung

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
sumber
2

Kami dapat menghitung persimpangan minus gabungan daftar:

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

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

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

Ini dapat diselesaikan dengan satu baris. Pertanyaan diberikan dua daftar (temp1 dan temp2) mengembalikan perbedaannya dalam daftar ketiga (temp3).

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

Berikut adalah cara sederhana untuk membedakan dua daftar (apa pun isinya), Anda bisa mendapatkan hasilnya seperti yang ditunjukkan di bawah ini:

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

Semoga ini bisa membantu.

SK Venkat
sumber
0

Saya lebih suka menggunakan konversi ke set dan kemudian menggunakan fungsi "perbedaan ()". Kode lengkapnya adalah:

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

Keluaran:

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

Ini paling mudah untuk dipahami, dan lebih baik lagi jika Anda bekerja dengan data besar, mengonversinya ke set akan menghapus duplikat jika duplikat tidak diperlukan. Semoga bisa membantu ;-)

Shakhyar Gogoi
sumber
-1
(list(set(a)-set(b))+list(set(b)-set(a)))
nadhem
sumber
3
Selain memberikan jawaban, dapatkah Anda memberikan penjelasan tentang cara kerjanya / berlaku untuk masalah khusus ini? Jawaban dan solusi bagus, tetapi panduan dan penjelasan terperinci jauh lebih baik.
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)))

mis. jika list1 = [10, 15, 20, 25, 30, 35, 40]dan list2 = [25, 40, 35]kemudian daftar yang dikembalikan adalahoutput = [10, 20, 30, 15]

csg
sumber
Anda tidak dapat melakukan seperti ini untuk operasi perbedaan. Bahkan dalam kasus bilangan bulat, jika Anda memberi tahu fungsi untuk melakukan 'a - b', itu seharusnya mengurangi 'b' dari 'a' saja, tidak masalah jika 'b' lebih besar dari 'a' atau sebaliknya. Serupa halnya dengan daftar dan set. A - B dan B - A keduanya dapat menjadi operasi yang valid terlepas dari panjang A dan B, Anda hanya perlu mengecualikan konten B dari A untuk melakukan A - B.
Abu Talha Denmark