Membandingkan dua kamus dan memeriksa jumlah pasangan (kunci, nilai) yang sama

246

Saya memiliki dua kamus, tetapi untuk penyederhanaan, saya akan mengambil dua ini:

>>> x = dict(a=1, b=2)
>>> y = dict(a=2, b=2)

Sekarang, saya ingin membandingkan apakah masing-masing key, valuepasangan xmemiliki nilai yang sesuai di y. Jadi saya menulis ini:

>>> for x_values, y_values in zip(x.iteritems(), y.iteritems()):
        if x_values == y_values:
            print 'Ok', x_values, y_values
        else:
            print 'Not', x_values, y_values

Dan itu berfungsi sejak a tupledikembalikan dan kemudian dibandingkan untuk kesetaraan.

Pertanyaan saya:

Apakah ini benar? Apakah ada cara yang lebih baik untuk melakukan ini? Lebih baik tidak dalam kecepatan, saya berbicara tentang keanggunan kode.

UPDATE: Saya lupa menyebutkan bahwa saya harus memeriksa berapa key, valuepasangan yang sama.

pengguna225312
sumber
21
x == yharus benar sesuai dengan stackoverflow.com/a/5635309/186202
Natim
x == y harus benar. Orang dapat dengan cepat memeriksa REPL. Silakan Rujuk: docs.python.org/2/library/stdtypes.html#mapping-types-dict
Vikrant

Jawaban:

179

Jika Anda ingin tahu berapa banyak nilai yang cocok dengan kedua kamus, Anda harus mengatakan itu :)

Mungkin kira-kira seperti ini:

shared_items = {k: x[k] for k in x if k in y and x[k] == y[k]}
print len(shared_items)
mouad
sumber
1
Kesalahan yang sama jika ada elemen daftar untuk kunci dict. Saya pikir cmp adalah cara yang lebih baik untuk melakukannya kecuali saya kehilangan sesuatu.
Mutant
@Mutant itu adalah masalah yang berbeda. Anda tidak dapat membuat kamus dengan listkunci di tempat pertama. x = {[1,2]: 2}akan gagal. Pertanyaannya sudah valid dicts.
AnnanFay
@annan: salah, pertanyaannya generik. yang misalnya dalam deskripsi tersebut memiliki sudah "dicts valid". Jika saya memposting pertanyaan baru, dengan judul yang sama, tetapi dengan dict "tidak valid" yang berbeda, seseorang akan menandainya sebagai duplikat. Downvoting.
ribamar
6
@ribamar pertanyaannya adalah "Membandingkan dua kamus [...]". 'Dict tidak valid' di atas dengan listkunci bukan kode python yang valid - kunci dict harus tidak berubah. Karena itu Anda tidak membandingkan kamus. Jika Anda mencoba dan menggunakan daftar sebagai kunci kamus, kode Anda tidak akan berjalan. Anda tidak memiliki objek untuk dibandingkan. Ini seperti mengetik x = dict(23\;dfg&^*$^%$^$%^)lalu mengeluh bagaimana perbandingan tidak berfungsi dengan kamus. Tentu saja itu tidak akan berhasil. Komentar Tim di sisi lain adalah tentang bisa berubah values, maka mengapa saya mengatakan bahwa ini adalah masalah yang berbeda.
AnnanFay
1
@MikeyE - setmembutuhkan nilai yang harus hashable dan dictmembutuhkan kunci yang harus hashable. set(x.keys())akan selalu berfungsi karena kunci diharuskan untuk hashable, tetapi set(x.values())akan gagal pada nilai yang tidak hashable.
Tim Tisdall
173

Yang ingin Anda lakukan hanyalah sederhana x==y

Apa yang Anda lakukan bukanlah ide yang baik, karena barang-barang dalam kamus tidak seharusnya dipesan. Anda mungkin membandingkan [('a',1),('b',1)]dengan[('b',1), ('a',1)] (kamus yang sama, urutan berbeda).

Sebagai contoh, lihat ini:

>>> x = dict(a=2, b=2,c=3, d=4)
>>> x
{'a': 2, 'c': 3, 'b': 2, 'd': 4}
>>> y = dict(b=2,c=3, d=4)
>>> y
{'c': 3, 'b': 2, 'd': 4}
>>> zip(x.iteritems(), y.iteritems())
[(('a', 2), ('c', 3)), (('c', 3), ('b', 2)), (('b', 2), ('d', 4))]

Perbedaannya hanya satu item, tetapi algoritma Anda akan melihat bahwa semua item berbeda

Jochen Ritzel
sumber
@ THC4k, maaf karena tidak menyebutkan. Tetapi saya harus memeriksa berapa banyak nilai yang cocok dengan kedua kamus tersebut.
user225312
Ok, jadi berdasarkan pembaruan saya, apakah cara saya masih salah?
user225312
@ AA: Saya menambahkan mengapa Anda tidak berfungsi saat Anda ingin menghitung.
Jochen Ritzel
Saya mengerti, tetapi dalam kasus saya kedua kamus itu memiliki panjang yang sama. Dan mereka akan selalu demikian, karena begitulah program bekerja.
user225312
5
Pada Python 3.6, dikt adalah orderd out-of-the-box.
Phil
163
def dict_compare(d1, d2):
    d1_keys = set(d1.keys())
    d2_keys = set(d2.keys())
    shared_keys = d1_keys.intersection(d2_keys)
    added = d1_keys - d2_keys
    removed = d2_keys - d1_keys
    modified = {o : (d1[o], d2[o]) for o in shared_keys if d1[o] != d2[o]}
    same = set(o for o in shared_keys if d1[o] == d2[o])
    return added, removed, modified, same

x = dict(a=1, b=2)
y = dict(a=2, b=2)
added, removed, modified, same = dict_compare(x, y)
Daniel Myers
sumber
7
Yang satu ini benar-benar menangani nilai yang bisa berubah dalam dikt!
Tim Tisdall
1
Ketika saya menjalankan ini, saya masih mendapatkan kesalahan melihat berurusan dengan nilai-nilai yang bisa berubah: ValueError: Nilai kebenaran dari DataFrame ambigu. Gunakan a.empty, a.bool (), a.item (), a.any () atau a.all ().
Afflatus
2
@ Afffus - DataFramemenurut desain tidak memungkinkan perbandingan yang benar (kecuali jika memiliki panjang 1) karena mereka mewarisi dari numpy.ndarray. -credit to stackoverflow.com/a/33307396/994076
Daniel Myers
Ini adalah permata mutlak.
pfabri
125

dic1 == dic2

Dari python docs :

Untuk mengilustrasikan, contoh-contoh berikut semua mengembalikan kamus sama dengan {"one": 1, "two": 2, "three": 3}:

>>> a = dict(one=1, two=2, three=3)
>>> b = {'one': 1, 'two': 2, 'three': 3}
>>> c = dict(zip(['one', 'two', 'three'], [1, 2, 3]))
>>> d = dict([('two', 2), ('one', 1), ('three', 3)])
>>> e = dict({'three': 3, 'one': 1, 'two': 2})
>>> a == b == c == d == e
True

Memberikan argumen kata kunci seperti pada contoh pertama hanya berfungsi untuk kunci yang merupakan pengidentifikasi Python yang valid. Kalau tidak, kunci apa pun yang valid dapat digunakan.

Berlaku untuk keduanya py2dan py3.

HUBUNGI19
sumber
3
Saya tidak setuju dengan @ ErkinAlpGüney. Bisakah Anda memberikan bukti?
Qi Luo
4
Saya tidak setuju dengan @ ErkinAlpGüney. Dokumentasi resmi menunjukkan bahwa == memang membandingkan kamus dengan nilai, bukan dengan alamat. docs.python.org/2/library/stdtypes.html#mapping-types-dict
Matthew Nakayama
3
Bekerja untuk Python 2.7.13
Jesuisme
4
@ankostis:OrderedDict != dict
CONvid19
3
Bisakah Anda memberikan masukan di tempat ini tidak benar?
CONvid19
55

Saya baru mengenal python tapi akhirnya saya melakukan sesuatu yang mirip dengan @mouad

unmatched_item = set(dict_1.items()) ^ set(dict_2.items())
len(unmatched_item) # should be 0

Operator XOR ( ^) harus menghilangkan semua elemen dict ketika keduanya sama di kedua dicts.

philipp
sumber
28
Sayangnya ini tidak berfungsi jika nilai-nilai dalam dikt bisa berubah-ubah (mis. Tidak hashable). (Kel {'a':{'b':1}}memberikan TypeError: unhashable type: 'dict')
Tim Tisdall
54

Karena sepertinya tidak ada yang disebutkan deepdiff, saya akan menambahkannya di sini untuk kelengkapan. Saya merasa sangat nyaman untuk mendapatkan objek yang berbeda (bersarang) secara umum:

Instalasi

pip install deepdiff

Kode sampel

import deepdiff
import json

dict_1 = {
    "a": 1,
    "nested": {
        "b": 1,
    }
}

dict_2 = {
    "a": 2,
    "nested": {
        "b": 2,
    }
}

diff = deepdiff.DeepDiff(dict_1, dict_2)
print(json.dumps(diff, indent=4))

Keluaran

{
    "values_changed": {
        "root['a']": {
            "new_value": 2,
            "old_value": 1
        },
        "root['nested']['b']": {
            "new_value": 2,
            "old_value": 1
        }
    }
}

Catatan tentang pencetakan cantik hasil untuk pemeriksaan: Kode di atas berfungsi jika kedua dikte memiliki kunci atribut yang sama (dengan nilai atribut yang mungkin berbeda seperti pada contoh). Namun, jika suatu "extra"atribut hadir adalah salah satu dicts, json.dumps()gagal dengan

TypeError: Object of type PrettyOrderedSet is not JSON serializable

Solusi: gunakan diff.to_json()dan json.loads()/ json.dumps()untuk mencetak-cantik:

import deepdiff
import json

dict_1 = {
    "a": 1,
    "nested": {
        "b": 1,
    },
    "extra": 3
}

dict_2 = {
    "a": 2,
    "nested": {
        "b": 2,
    }
}

diff = deepdiff.DeepDiff(dict_1, dict_2)
print(json.dumps(json.loads(diff.to_json()), indent=4))  

Keluaran:

{
    "dictionary_item_removed": [
        "root['extra']"
    ],
    "values_changed": {
        "root['a']": {
            "new_value": 2,
            "old_value": 1
        },
        "root['nested']['b']": {
            "new_value": 2,
            "old_value": 1
        }
    }
}

Alternatif: gunakan pprint, menghasilkan pemformatan yang berbeda:

import pprint

# same code as above

pprint.pprint(diff, indent=4)

Keluaran:

{   'dictionary_item_removed': [root['extra']],
    'values_changed': {   "root['a']": {   'new_value': 2,
                                           'old_value': 1},
                          "root['nested']['b']": {   'new_value': 2,
                                                     'old_value': 1}}}
Sumudu
sumber
2
Menarik. Terima kasih telah menjawab ini. Berguna bagi saya minimal. Jawaban ini perlu lebih banyak upvotes.
Archit Kapoor
46

Cukup gunakan:

assert cmp(dict1, dict2) == 0
Shiyu
sumber
6
Tampaknya tugasnya tidak hanya untuk memeriksa apakah isi keduanya sama tetapi juga untuk memberikan laporan perbedaan
Diego Tercero
29
Saya percaya ini identik dengandict1 == dict2
Trey Hunner
10
Bagi siapa pun yang menggunakan Python3.5, cmpbuilt-in telah dihapus (dan harus diperlakukan sebagai dihapus sebelumnya . Alternatif yang mereka usulkan: (a > b) - (a < b) == cmp(a, b)untuk fungsional yang setara (atau lebih baik __eq__dan __hash__)
nerdwaller
3
@nerdwaller - dicts bukan tipe yang bisa dipesan, jadi dict_a> dict_b akan memunculkan TypeError:unorderable types: dict() < dict()
Stefano
2
@Stefano: Panggilan bagus, komentar saya lebih untuk perbandingan umum dengan python (saya tidak memperhatikan jawaban aktual, kesalahan saya).
nerdwaller
9

Jawaban @mouad bagus jika Anda menganggap bahwa kedua kamus hanya berisi nilai-nilai sederhana. Namun, jika Anda memiliki kamus yang berisi kamus Anda akan mendapatkan pengecualian karena kamus tidak dapat diacak.

Di atas kepala saya, sesuatu seperti ini mungkin bekerja:

def compare_dictionaries(dict1, dict2):
     if dict1 is None or dict2 is None:
        print('Nones')
        return False

     if (not isinstance(dict1, dict)) or (not isinstance(dict2, dict)):
        print('Not dict')
        return False

     shared_keys = set(dict1.keys()) & set(dict2.keys())

     if not ( len(shared_keys) == len(dict1.keys()) and len(shared_keys) == len(dict2.keys())):
        print('Not all keys are shared')
        return False


     dicts_are_equal = True
     for key in dict1.keys():
         if isinstance(dict1[key], dict) or isinstance(dict2[key], dict):
             dicts_are_equal = dicts_are_equal and compare_dictionaries(dict1[key], dict2[key])
         else:
             dicts_are_equal = dicts_are_equal and all(atleast_1d(dict1[key] == dict2[key]))

     return dicts_are_equal
Alexander
sumber
Jika Anda menggunakan not isinstance(dict1, dict)alih-alih type(dict1) is not dict, ini akan bekerja pada kelas lain berdasarkan pada dict. Also, instead of (dict1 [key] == dict2 [key]) , you can do semua (atleast_1d (dict1 [key] == dict2 [key])) `untuk menangani array setidaknya.
EL_DON
+1, tetapi Anda bisa keluar for loopsegera setelah Anda dicts_are_equalmenjadi salah. Tidak perlu melanjutkan lebih jauh.
pfabri
6

Namun kemungkinan lain, hingga catatan terakhir OP, adalah untuk membandingkan hash ( SHAatau MD) dari dikte yang dibuang sebagai JSON. Cara hash dibangun menjamin bahwa jika mereka sama, string sumbernya juga sama. Ini sangat cepat dan suara secara matematis.

import json
import hashlib

def hash_dict(d):
    return hashlib.sha1(json.dumps(d, sort_keys=True)).hexdigest()

x = dict(a=1, b=2)
y = dict(a=2, b=2)
z = dict(a=1, b=2)

print(hash_dict(x) == hash_dict(y))
print(hash_dict(x) == hash_dict(z))
WoJ
sumber
2
Benar-benar salah, hanya mem-parsing data ke json benar-benar lambat. Kemudian hashing sring besar yang baru saja Anda buat bahkan lebih buruk. Anda seharusnya tidak melakukan itu
Bruno
7
@ Bruno: mengutip OP: "Lebih baik tidak dalam kecepatan, saya berbicara tentang keanggunan kode"
WoJ
2
Sama sekali tidak elegan, rasanya tidak aman dan terlalu rumit untuk masalah yang sangat sederhana
Bruno
7
@ Bruno: keanggunan itu subyektif. Saya bisa mengerti bahwa Anda tidak menyukainya (dan mungkin downvoted). Ini tidak sama dengan "salah".
WoJ
4
Ini jawaban yang bagus. json.dumps(d, sort_keys=True)akan memberi Anda JSON kanonik sehingga Anda dapat yakin bahwa kedua diktuanya setara. Itu juga tergantung apa yang ingin Anda capai. Segera setelah nilainya tidak dapat diservis JSON, ia akan gagal. Untuk itu yang mengatakan itu tidak efisien, lihatlah proyek ujson.
Natim
6

Fungsinya IMO baik, jelas dan intuitif. Tapi hanya untuk memberi Anda (yang lain) jawaban, ini dia:

def compare_dict(dict1, dict2):
    for x1 in dict1.keys():
        z = dict1.get(x1) == dict2.get(x1)
        if not z:
            print('key', x1)
            print('value A', dict1.get(x1), '\nvalue B', dict2.get(x1))
            print('-----\n')

Dapat bermanfaat bagi Anda atau orang lain ..

EDIT:

Saya telah membuat versi rekursif dari yang di atas .. Belum melihat jawaban yang lain

def compare_dict(a, b):
    # Compared two dictionaries..
    # Posts things that are not equal..
    res_compare = []
    for k in set(list(a.keys()) + list(b.keys())):
        if isinstance(a[k], dict):
            z0 = compare_dict(a[k], b[k])
        else:
            z0 = a[k] == b[k]

        z0_bool = np.all(z0)
        res_compare.append(z0_bool)
        if not z0_bool:
            print(k, a[k], b[k])
    return np.all(res_compare)
zwep
sumber
2
Mari kita tingkatkan sehingga itu berfungsi dua arah. Baris 2: "untuk x1 pada set (dict1.keys ()). Union (dict2.keys ()):"
nkadwa
Terima kasih @nkadwa, sekarang
zwep
5

Untuk menguji apakah dua dicts sama dalam kunci dan nilai:

def dicts_equal(d1,d2):
    """ return True if all keys and values are the same """
    return all(k in d2 and d1[k] == d2[k]
               for k in d1) \
        and all(k in d1 and d1[k] == d2[k]
               for k in d2)

Jika Anda ingin mengembalikan nilai yang berbeda, tulis secara berbeda:

def dict1_minus_d2(d1, d2):
    """ return the subset of d1 where the keys don't exist in d2 or
        the values in d2 are different, as a dict """
    return {k,v for k,v in d1.items() if k in d2 and v == d2[k]}

Anda harus menyebutnya dua kali yaitu

dict1_minus_d2(d1,d2).extend(dict1_minus_d2(d2,d1))
simonltwick
sumber
3

Kode

def equal(a, b):
    type_a = type(a)
    type_b = type(b)
    
    if type_a != type_b:
        return False
    
    if isinstance(a, dict):
        if len(a) != len(b):
            return False
        for key in a:
            if key not in b:
                return False
            if not equal(a[key], b[key]):
                return False
        return True

    elif isinstance(a, list):
        if len(a) != len(b):
            return False
        while len(a):
            x = a.pop()
            index = indexof(x, b)
            if index == -1:
                return False
            del b[index]
        return True
        
    else:
        return a == b

def indexof(x, a):
    for i in range(len(a)):
        if equal(x, a[i]):
            return i
    return -1

Uji

>>> a = {
    'number': 1,
    'list': ['one', 'two']
}
>>> b = {
    'list': ['two', 'one'],
    'number': 1
}
>>> equal(a, b)
True
Yas
sumber
3

Perbandingan sederhana dengan == sudah cukup saat ini (python 3.8). Bahkan ketika Anda membandingkan dict yang sama dalam urutan yang berbeda (contoh terakhir). Yang terbaik adalah, Anda tidak perlu paket pihak ketiga untuk mencapai ini.

a = {'one': 'dog', 'two': 'cat', 'three': 'mouse'}
b = {'one': 'dog', 'two': 'cat', 'three': 'mouse'}

c = {'one': 'dog', 'two': 'cat', 'three': 'mouse'}
d = {'one': 'dog', 'two': 'cat', 'three': 'mouse', 'four': 'fish'}

e = {'one': 'cat', 'two': 'dog', 'three': 'mouse'}
f = {'one': 'dog', 'two': 'cat', 'three': 'mouse'}

g = {'two': 'cat', 'one': 'dog', 'three': 'mouse'}
h = {'one': 'dog', 'two': 'cat', 'three': 'mouse'}


print(a == b) # True
print(c == d) # False
print(e == f) # False
print(g == h) # True
Nebulastik
sumber
2

Terlambat dalam respons saya lebih baik daripada tidak pernah!

Bandingkan Not_Equal lebih efisien daripada membandingkan Equal. Dengan demikian, dua dict tersebut tidak sama jika nilai kunci dalam satu dict tidak ditemukan di dict lainnya. Kode di bawah ini mempertimbangkan bahwa Anda mungkin membandingkan dict default dan karenanya menggunakan get bukannya getitem [].

Menggunakan semacam nilai acak sebagai default dalam panggilan panggil sama dengan kunci yang diambil - untuk jaga-jaga jika dicts memiliki nilai None sebagai dalam satu dict dan kunci tersebut tidak ada di yang lain. Juga kondisi get! = Diperiksa sebelum tidak dalam kondisi untuk efisiensi karena Anda melakukan pemeriksaan pada kunci dan nilai dari kedua sisi pada saat yang sama.

def Dicts_Not_Equal(first,second):
    """ return True if both do not have same length or if any keys and values are not the same """
    if len(first) == len(second): 
        for k in first:
            if first.get(k) != second.get(k,k) or k not in second: return (True)
        for k in second:         
            if first.get(k,k) != second.get(k) or k not in first: return (True)
        return (False)   
    return (True)
pengguna-asterix
sumber
2

Saya menggunakan solusi ini yang bekerja sempurna untuk saya di Python 3


import logging
log = logging.getLogger(__name__)

...

    def deep_compare(self,left, right, level=0):
        if type(left) != type(right):
            log.info("Exit 1 - Different types")
            return False

        elif type(left) is dict:
            # Dict comparison
            for key in left:
                if key not in right:
                    log.info("Exit 2 - missing {} in right".format(key))
                    return False
                else:
                    if not deep_compare(left[str(key)], right[str(key)], level +1 ):
                        log.info("Exit 3 - different children")
                        return False
            return True
        elif type(left) is list:
            # List comparison
            for key in left:
                if key not in right:
                    log.info("Exit 4 - missing {} in right".format(key))
                    return False
                else:
                    if not deep_compare(left[left.index(key)], right[right.index(key)], level +1 ):
                        log.info("Exit 5 - different children")
                        return False
            return True
        else:
            # Other comparison
            return left == right

        return False

Ini membandingkan dict, daftar, dan jenis lainnya yang mengimplementasikan operator "==" sendiri. Jika Anda perlu membandingkan sesuatu yang berbeda, Anda perlu menambahkan cabang baru di "if tree".

Semoga itu bisa membantu.

Giovanni Basolu
sumber
2

untuk python3:

data_set_a = dict_a.items()
data_set_b = dict_b.items()

difference_set = data_set_a ^ data_set_b
Bryant
sumber
1
>>> hash_1
{'a': 'foo', 'b': 'bar'}
>>> hash_2
{'a': 'foo', 'b': 'bar'}
>>> set_1 = set (hash_1.iteritems())
>>> set_1
set([('a', 'foo'), ('b', 'bar')])
>>> set_2 = set (hash_2.iteritems())
>>> set_2
set([('a', 'foo'), ('b', 'bar')])
>>> len (set_1.difference(set_2))
0
>>> if (len(set_1.difference(set_2)) | len(set_2.difference(set_1))) == False:
...    print "The two hashes match."
...
The two hashes match.
>>> hash_2['c'] = 'baz'
>>> hash_2
{'a': 'foo', 'c': 'baz', 'b': 'bar'}
>>> if (len(set_1.difference(set_2)) | len(set_2.difference(set_1))) == False:
...     print "The two hashes match."
...
>>>
>>> hash_2.pop('c')
'baz'

Ini pilihan lain:

>>> id(hash_1)
140640738806240
>>> id(hash_2)
140640738994848

Jadi seperti yang Anda lihat, kedua id berbeda. Tapi operator pembanding kaya sepertinya melakukan trik:

>>> hash_1 == hash_2
True
>>>
>>> hash_2
{'a': 'foo', 'b': 'bar'}
>>> set_2 = set (hash_2.iteritems())
>>> if (len(set_1.difference(set_2)) | len(set_2.difference(set_1))) == False:
...     print "The two hashes match."
...
The two hashes match.
>>>
Dipimpin Zeppelin
sumber
1

Di PyUnit ada metode yang membandingkan kamus dengan indah. Saya mengujinya menggunakan dua kamus berikut, dan ia melakukan apa yang Anda cari.

d1 = {1: "value1",
      2: [{"subKey1":"subValue1",
           "subKey2":"subValue2"}]}
d2 = {1: "value1",
      2: [{"subKey2":"subValue2",
           "subKey1": "subValue1"}]
      }


def assertDictEqual(self, d1, d2, msg=None):
        self.assertIsInstance(d1, dict, 'First argument is not a dictionary')
        self.assertIsInstance(d2, dict, 'Second argument is not a dictionary')

        if d1 != d2:
            standardMsg = '%s != %s' % (safe_repr(d1, True), safe_repr(d2, True))
            diff = ('\n' + '\n'.join(difflib.ndiff(
                           pprint.pformat(d1).splitlines(),
                           pprint.pformat(d2).splitlines())))
            standardMsg = self._truncateMessage(standardMsg, diff)
            self.fail(self._formatMessage(msg, standardMsg))

Saya tidak merekomendasikan mengimpor unittestke kode produksi Anda. Pikiran saya adalah sumber di PyUnit dapat digunakan kembali untuk berjalan dalam produksi. Ini menggunakan pprint"cetakan cantik" kamus. Tampaknya mudah untuk mengadaptasi kode ini menjadi "siap produksi".

MikeyE
sumber
1

lihat objek tampilan kamus: https://docs.python.org/2/library/stdtypes.html#dict

Dengan cara ini Anda dapat mengurangi dictView2 dari dictView1 dan itu akan mengembalikan satu set pasangan kunci / nilai yang berbeda di dictView2:

original = {'one':1,'two':2,'ACTION':'ADD'}
originalView=original.viewitems()
updatedDict = {'one':1,'two':2,'ACTION':'REPLACE'}
updatedDictView=updatedDict.viewitems()
delta=original | updatedDict
print delta
>>set([('ACTION', 'REPLACE')])

Anda dapat memotong, menyatukan, perbedaan (ditampilkan di atas), perbedaan simetris objek tampilan kamus ini.
Lebih baik? Lebih cepat? - tidak yakin, tetapi bagian dari perpustakaan standar - yang membuatnya menjadi nilai tambah yang besar untuk portabilitas

tranimatronic
sumber
1

Kode di bawah ini akan membantu Anda membandingkan daftar dict dengan python

def compate_generic_types(object1, object2):
    if isinstance(object1, str) and isinstance(object2, str):
        return object1 == object2
    elif isinstance(object1, unicode) and isinstance(object2, unicode):
        return object1 == object2
    elif isinstance(object1, bool) and isinstance(object2, bool):
        return object1 == object2
    elif isinstance(object1, int) and isinstance(object2, int):
        return object1 == object2
    elif isinstance(object1, float) and isinstance(object2, float):
        return object1 == object2
    elif isinstance(object1, float) and isinstance(object2, int):
        return object1 == float(object2)
    elif isinstance(object1, int) and isinstance(object2, float):
        return float(object1) == object2

    return True

def deep_list_compare(object1, object2):
    retval = True
    count = len(object1)
    object1 = sorted(object1)
    object2 = sorted(object2)
    for x in range(count):
        if isinstance(object1[x], dict) and isinstance(object2[x], dict):
            retval = deep_dict_compare(object1[x], object2[x])
            if retval is False:
                print "Unable to match [{0}] element in list".format(x)
                return False
        elif isinstance(object1[x], list) and isinstance(object2[x], list):
            retval = deep_list_compare(object1[x], object2[x])
            if retval is False:
                print "Unable to match [{0}] element in list".format(x)
                return False
        else:
            retval = compate_generic_types(object1[x], object2[x])
            if retval is False:
                print "Unable to match [{0}] element in list".format(x)
                return False

    return retval

def deep_dict_compare(object1, object2):
    retval = True

    if len(object1) != len(object2):
        return False

    for k in object1.iterkeys():
        obj1 = object1[k]
        obj2 = object2[k]
        if isinstance(obj1, list) and isinstance(obj2, list):
            retval = deep_list_compare(obj1, obj2)
            if retval is False:
                print "Unable to match [{0}]".format(k)
                return False

        elif isinstance(obj1, dict) and isinstance(obj2, dict):
            retval = deep_dict_compare(obj1, obj2)
            if retval is False:
                print "Unable to match [{0}]".format(k)
                return False
        else:
            retval = compate_generic_types(obj1, obj2)
            if retval is False:
                print "Unable to match [{0}]".format(k)
                return False

    return retval
Vitthal Kadam
sumber
3
Selamat Datang di Stack Overflow! Sementara potongan kode ini dapat menyelesaikan pertanyaan, termasuk penjelasan sangat membantu untuk meningkatkan kualitas posting Anda. Ingatlah bahwa Anda menjawab pertanyaan untuk pembaca di masa depan, dan orang-orang itu mungkin tidak tahu alasan untuk saran kode Anda. Tolong juga cobalah untuk tidak membuat kerumunan kode Anda dengan komentar penjelasan, ini mengurangi keterbacaan kode dan penjelasan!
Filnor
1
>>> x = {'a':1,'b':2,'c':3}
>>> x
{'a': 1, 'b': 2, 'c': 3}

>>> y = {'a':2,'b':4,'c':3}
>>> y
{'a': 2, 'b': 4, 'c': 3}

METHOD 1:

>>> common_item = x.items()&y.items() #using union,x.item() 
>>> common_item
{('c', 3)}

METHOD 2:

 >>> for i in x.items():
        if i in y.items():
           print('true')
        else:
           print('false')


false
false
true
vidiv
sumber
0

Dalam Python 3.6, Ini dapat dilakukan sebagai: -

if (len(dict_1)==len(dict_2): 
  for i in dict_1.items():
        ret=bool(i in dict_2.items())

variabel ret akan benar jika semua item dict_1 hadir di dict_2

Souravi Sinha
sumber
0

Inilah jawaban saya, gunakan cara rekursif:

def dict_equals(da, db):
    if not isinstance(da, dict) or not isinstance(db, dict):
        return False
    if len(da) != len(db):
        return False
    for da_key in da:
        if da_key not in db:
            return False
        if not isinstance(db[da_key], type(da[da_key])):
            return False
        if isinstance(da[da_key], dict):
            res = dict_equals(da[da_key], db[da_key])
            if res is False:
                return False
        elif da[da_key] != db[da_key]:
            return False
    return True

a = {1:{2:3, 'name': 'cc', "dd": {3:4, 21:"nm"}}}
b = {1:{2:3, 'name': 'cc', "dd": {3:4, 21:"nm"}}}
print dict_equals(a, b)

Semoga itu bisa membantu!

William Xu
sumber
0

Mengapa tidak hanya beralih melalui satu kamus dan memeriksa kamus lain dalam proses (dengan asumsi kedua kamus memiliki kunci yang sama)?

x = dict(a=1, b=2)
y = dict(a=2, b=2)

for key, val in x.items():
    if val == y[key]:
        print ('Ok', val, y[key])
    else:
        print ('Not', val, y[key])

Keluaran:

Not 1 2
Ok 2 2
LEB
sumber
0

Cara termudah (dan salah satu yang lebih kuat pada saat itu) untuk melakukan perbandingan yang mendalam dari dua kamus adalah dengan membuat serial mereka dalam format JSON, mengurutkan kunci, dan membandingkan hasil string:

import json
if json.dumps(x, sort_keys=True) == json.dumps(y, sort_keys=True):
   ... Do something ...
Krasimir Kalinov Kostadinov
sumber
-7
import json

if json.dumps(dict1) == json.dumps(dict2):
    print("Equal")
Mariusz K
sumber
1
Ini mungkin tidak melakukan apa yang diminta secara tepat, dan menarik json std lib, tetapi tidak berfungsi (seperti json.dumpsyang ditentukan dengan pengaturan default).
Daniel Farrell