İki sözlüğü karşılaştırma ve kaç (anahtar, değer) çiftinin eşit olduğunu kontrol etme


246

İki sözlüküm var, ancak basitleştirmek için bu ikisini alacağım:

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

Şimdi, her key, valueçiftin xaynı karşılık gelen değere sahip olup olmadığını karşılaştırmak istiyorum y. Bu yüzden şunu yazdım:

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

Ve a tupledöndüğünden beri çalışır ve daha sonra eşitlik için karşılaştırılır.

Sorularım:

Bu doğru mu? Bunu yapmanın daha iyi bir yolu var mı ? Daha hızlı olmasa da, kod zarafetinden bahsediyorum.

GÜNCELLEME: Kaç key, valueçiftin eşit olduğunu kontrol etmem gerektiğini belirtmeyi unuttum .



x == y doğru olmalı. Hızlı bir şekilde REPL kontrol edebilirsiniz. Lütfen Bakın: docs.python.org/2/library/stdtypes.html#mapping-types-dict
Vikrant

Yanıtlar:


179

Her iki sözlükte kaç değerin eşleştiğini bilmek istiyorsanız, şunu söylemeliydiniz :)

Belki böyle bir şey:

shared_items = {k: x[k] for k in x if k in y and x[k] == y[k]}
print len(shared_items)

1
Dict anahtarı için liste öğesi varsa aynı hata. Ben bir şey eksik sürece cmp bunu yapmak için daha iyi bir yol olduğunu düşünüyorum.
Mutant

@Mutant farklı bir konudur. listİlk etapta bir anahtarla sözlük oluşturamazsınız . x = {[1,2]: 2}başaramayacak. Soru zaten geçerli dicts.
AnnanFay

@annan: yanlış, soru genel. örnek soru açıklamasında zaten "geçerli dicts" vardır. Aynı başlıkta, ancak farklı bir "geçersiz" dikte ile yeni bir soru gönderirsem, biri bunu yinelenen olarak işaretler. Downvoting.
ribamar

6
@ribamar soru "İki sözlük karşılaştırılıyor [...]". Yukarıdaki listanahtarlarla birlikte 'geçersiz dik' geçerli python kodu değil - dik tuşlarının değişmez olması gerekir. Bu nedenle sözlükleri karşılaştırmıyorsunuz. Bir listeyi sözlük anahtarı olarak kullanmayı denerseniz, kodunuz çalışmaz. Karşılaştırılacak nesneniz yok. Bu, yazmaktan x = dict(23\;dfg&^*$^%$^$%^)sonra karşılaştırmanın sözlükle nasıl çalışmadığından şikayet etmektir. Tabii ki işe yaramayacak. Tim'in öte yandan yorumu değişebilir values, bu yüzden bunların farklı konular olduğunu söyledim.
AnnanFay

1
@MikeyE - setdeğerlerin yıkanabilir olmasını ve dictanahtarların yıkanabilir olmasını gerektirir. set(x.keys())anahtarların yıkanabilir olması gerektiğinden daima çalışır, ancak yıkanamayan set(x.values())değerlerde başarısız olur.
Tim Tisdall

173

Yapmak istediğin şey basitçe x==y

Yaptığınız şey iyi bir fikir değil, çünkü sözlükteki öğelerin herhangi bir sıraya sahip olması gerekmiyor. (Aynı sözlükler, farklı düzen) [('a',1),('b',1)]ile karşılaştırıyor olabilirsiniz [('b',1), ('a',1)].

Örneğin, şuna bakın:

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

Fark sadece bir öğe, ancak algoritmanız tüm öğelerin farklı olduğunu görecek


@ THC4k, bahsetmediğim için üzgünüm. Ama her iki sözlükte de kaç değer eşleştiğini kontrol etmeliyim.
user225312

Tamam, güncellememe dayanarak, hala yapma şeklim yanlış mı?
user225312

@AA: Saymak istediğinizde niçin işe yaramadığını ekledim.
Jochen Ritzel

Anlıyorum, ama benim durumumda her iki sözlük de aynı uzunluktadır. Ve her zaman olacaklar, çünkü program böyle çalışır.
user225312

5
Python 3.6'dan itibaren, söz konusu kutu kutudan çıkarılır.
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)

7
Bu aslında dikte değişebilir değerleri ele!
Tim Tisdall

1
Bunu çalıştırdığımda, hala değişebilir değerlerle ilgili bir hata alıyorum: ValueError: Bir DataFrame gerçek değeri belirsiz. A.empty, a.bool (), a.item (), a.any () veya a.all () kullanın.
Afflatus

2
@Afflatus - DataFramelar tasarımdan miras olarak doğruluksal karşılaştırmalara izin vermezler (uzunluğu 1 olmadığı sürece) numpy.ndarray. kredi için stackoverflow.com/a/33307396/994076
Daniel Myers

Bu mutlak bir mücevher olduğunu.
pfabri

125

dic1 == dic2

Gönderen piton docs :

Örnek olarak, aşağıdaki örnekler hepsi bir sözlük dönmek eşit için {"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

İlk örnekte olduğu gibi anahtar kelime bağımsız değişkenleri sağlamak yalnızca geçerli Python tanımlayıcıları olan anahtarlar için geçerlidir. Aksi takdirde, geçerli herhangi bir anahtar kullanılabilir.

Her ikisi için de geçerlidir py2ve py3.


3
@ ErkinAlpGüney ile aynı fikirde değilim. Bir kanıt verebilir misiniz?
Qi Luo

4
@ ErkinAlpGüney ile aynı fikirde değilim. Resmi belgeler == ifadesinin sözlükleri adresle değil, değerle karşılaştırdığını göstermektedir. docs.python.org/2/library/stdtypes.html#mapping-types-dict
Matthew Nakayama

3
Python 2.7.13
Jesuisme

4
@ankostis:OrderedDict != dict
CONvid19

3
Lütfen bunun doğru olmadığı bir girdi sağlayabilir misiniz?
CONvid19

55

Python'da yeniyim ama sonunda @mouad benzeri bir şey yaptım

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

XOR operatörü ( ^), her iki dikte de aynı olduğunda diktenin tüm öğelerini ortadan kaldırmalıdır.


28
Ne yazık ki, söz konusu değerler değiştirilebiliyorsa (yani yıkanamazsa) işe yaramaz. (Eski {'a':{'b':1}}verir TypeError: unhashable type: 'dict')
Tim Tisdall

54

Kimseden bahsetmediği deepdiffiçin buraya eksiksizlik için ekleyeceğim. Genel olarak (iç içe) nesnelerin farkını almak için çok uygun buluyorum:

Kurulum

pip install deepdiff

Basit kod

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

Çıktı

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

Sonucun incelenmek üzere güzel yazdırılmasıyla ilgili not: Yukarıdaki kod, her iki dikte de aynı öznitelik anahtarlarına sahipse çalışır (örnekte muhtemelen farklı öznitelik değerlerine sahip). Bir Ancak, "extra"bir özelliğin mevcut olup, dicts biri json.dumps()ile başarısız

TypeError: Object of type PrettyOrderedSet is not JSON serializable

Çözüm: Güzel yazdırmak için diff.to_json()ve json.loads()/ json.dumps()kullanın:

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

Çıktı:

{
    "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: kullanım pprint, farklı bir biçimlendirme ile sonuçlanır:

import pprint

# same code as above

pprint.pprint(diff, indent=4)

Çıktı:

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

2
İlginç. Bunu cevapladığınız için teşekkürler. En azından benim için kullanışlıdır. Bu cevap için daha fazla oy gerekiyor.
Archit Kapoor

46

Sadece kullan:

assert cmp(dict1, dict2) == 0

6
Görev sadece her ikisinin içeriğinin aynı olup olmadığını kontrol etmek değil, aynı zamanda farklılıklar hakkında bir rapor vermek gibi görünüyor
Diego Tercero

29
Bunun aynı olduğuna inanıyorumdict1 == dict2
Trey Hunner

10
Python3.5 kullanan herkes için cmpkaldırıldı yapılı (olarak ele alınmalıdır önce kaldırılmalıdır onlar teklif bir alternatif. (a > b) - (a < b) == cmp(a, b)İşlevsel bir eşdeğeri için (ya da daha iyi __eq__ve __hash__)
nerdwaller

3
@nerdwaller - diktiler düzenlenemez türler değildir, bu yüzden dict_a> dict_b bir TypeError:unorderable types: dict() < dict()
Stefano

2
@Stefano: İyi çağrı, yorumum python genel karşılaştırma için daha fazlaydı (gerçek cevaba, hataya dikkat etmiyordum).
nerdwaller

9

Her iki sözlükte de yalnızca basit değerler bulunduğunu varsayarsanız, @mouad'ın yanıtı güzeldir. Ancak, sözlük içeren sözlükleriniz varsa, sözlükler yıkanamaz olduğundan bir istisna alırsınız.

Başımın üstünde, böyle bir şey işe yarayabilir:

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

not isinstance(dict1, dict)Bunun yerine kullanırsanız type(dict1) is not dict, bu en azından dizileri işlemek için dict. Also, instead of (dict1 [key] == dict2 [key]) , you can do all (atleast_1d (dict1 [key] == dict2 [key])) `` tabanlı diğer sınıflar üzerinde çalışır .
EL_DON

+1, ancak yanlış olduğunuz for loopanda kendinizden dicts_are_equalayrılabilirsiniz. Daha fazla devam etmenize gerek yok.
pfabri

6

OP'nin son notasına kadar bir başka olasılık da JSON olarak atılan diktatların karmalarını ( SHAveya MD) karşılaştırmaktır . Hash'lerin oluşturulma şekli, eğer eşitlerse, kaynak dizgilerinin de eşit olduğunu garanti eder. Bu çok hızlı ve matematiksel olarak sağlam.

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

2
Bu tamamen yanlış, sadece verileri json'a ayrıştırmak gerçekten yavaş. Sonra az önce yarattığınız büyük sring hash daha da kötü. Bunu asla yapmamalısınız
Bruno

7
@Bruno: OP'den alıntı: "Daha hızlı değil, kod zarafetinden bahsediyorum"
WoJ

2
Hiç zarif değil, güvensiz hissediyor ve gerçekten basit bir sorun için aşırı derecede karmaşık
Bruno

7
@ Bruno: zarafet özneldir. Hoşunuza gitmediğini (ve muhtemelen indirildiğini) anlayabiliyorum. Bu "yanlış" ile aynı şey değildir.
WoJ

4
Bu harika bir cevap. json.dumps(d, sort_keys=True)kanonik JSON verecektir, böylece her iki diktenin eşdeğer olduğundan emin olabilirsiniz. Ayrıca, ne elde etmeye çalıştığınıza bağlıdır. Değer JSON serizalizable olmadığında başarısız olur. Bunun için verimsiz olduğunu söyleyenler için ujson projesine bir göz atın.
Natim

6

Fonksiyonu net IMO, net ve sezgisel. Ama sadece (başka) bir cevap vermek için işte şöyle:

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

Sizin için veya başka herhangi biri için yararlı olabilir.

DÜZENLE:

Ben yukarıdaki bir özyinelemeli sürümünü yarattık .. Diğer cevaplarda görmedim

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)

2
Bunu geliştirelim, böylece her iki şekilde de çalışır. Satır 2: "kümedeki x1 için (dict1.keys ()). Union (dict2.keys ()):"
nkadwa

Teşekkürler @nkadwa, şimdi
zwep

5

Anahtarlarda ve değerlerde iki diktemin eşit olup olmadığını test etmek için:

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)

Farklı değerleri döndürmek istiyorsanız, farklı yazın:

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

Bunu iki kez aramak zorundasınız yani

dict1_minus_d2(d1,d2).extend(dict1_minus_d2(d2,d1))

3

kod

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

Ölçek

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

3

Günümüzde == ile basit bir karşılaştırma yeterli olacaktır (python 3.8). Aynı dikmeleri farklı bir sırada karşılaştırdığınızda bile (son örnek). En iyisi, bunu gerçekleştirmek için üçüncü taraf bir pakete ihtiyacınız yok.

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

2

Cevabımda geç kalmak hiç olmadığı kadar iyi!

Karşılaştır Not_Equal, Eşit karşılaştırmaktan daha verimlidir. Çünkü bir dikte herhangi bir anahtar değer diğer dikte bulunmazsa, bu iki dikte eşit değildir. Aşağıdaki kod, varsayılan dikteyi karşılaştırabileceğinizi dikkate alır ve bu nedenle getitem [] yerine get komutunu kullanır .

Alma çağrısında alınan anahtarla eşit bir tür rastgele değer kullanmak - diktelerin bir dikte Yok olarak değeri olması ve diğerinde bulunmaması durumunda. Ayrıca get! = Koşulu, verimlilik için koşuldan önce kontrol edilir, çünkü aynı anda her iki taraftan anahtarları ve değerleri kontrol edersiniz.

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)

2

Python 3'te benim için mükemmel çalışan bu çözümü kullanıyorum


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

"==" operatörünü uygulayan dikt, liste ve diğer türleri karşılaştırır. Başka bir şeyi karşılaştırmanız gerekiyorsa, "eğer ağaç" a yeni bir dal eklemeniz gerekir.

Umarım yardımcı olur.


2

python3 için:

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

difference_set = data_set_a ^ data_set_b

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'

İşte başka bir seçenek:

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

Gördüğünüz gibi iki kimlik farklı. Ancak zengin karşılaştırma operatörleri hile yapıyor gibi görünüyor:

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

1

PyUnit'te sözlükleri güzel bir şekilde karşılaştıran bir yöntem var. Aşağıdaki iki sözlük kullanarak test ettim ve tam olarak aradığınızı yapıyor.

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

unittestÜretim kodunuza aktarmanızı önermiyorum . Benim düşüncem, PyUnit'teki kaynağın üretimde çalıştırmak için yeniden kullanılabileceğidir. pprintSözlükleri hangi "güzel yazdırır" kullanır . Bu kodu "üretime hazır" olacak şekilde uyarlamak oldukça kolay görünüyor.


1

sözlük görüntüleme nesnelerine bakın: https://docs.python.org/2/library/stdtypes.html#dict

Bu şekilde dictView2'yi dictView1'den çıkarabilirsiniz ve dictView2'de farklı olan bir dizi anahtar / değer çifti döndürür:

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

Bu sözlük görüntüleme nesnelerini kesişebilir, birleşebilir, fark (yukarıda gösterilmiştir), simetrik fark oluşturabilirsiniz.
Daha iyi? Daha hızlı? - emin değil, ama standart kütüphanenin bir parçası - taşınabilirlik için büyük bir artı


1

Aşağıdaki kod, python'daki dict listesini karşılaştırmanıza yardımcı olacaktır

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

3
Stack Overflow'a hoş geldiniz! Bu kod snippet'i soruyu çözebilir, ancak bir açıklama da dahil olmak üzere , yayınınızın kalitesini artırmaya yardımcı olur. Gelecekte okuyucular için soruyu cevapladığınızı ve bu kişilerin kod önerinizin nedenlerini bilmeyebileceğini unutmayın. Lütfen kodunuzu açıklayıcı yorumlarla doldurmamaya çalışın, bu hem kodun hem de açıklamaların okunabilirliğini azaltır!
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

0

Python 3.6, olarak yapılabilir: -

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

dict_2 içinde şu anda tüm dict_1 öğeleri varsa ret değişkeni true olur


0

İşte cevabım, yinelenen bir yol kullanın:

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)

Umarım yardımcı olur!


0

Neden sadece bir sözlük üzerinden yineleme yapıp diğerini kontrol etmiyorsunuz (her iki sözlükte de aynı anahtarların olduğu varsayılarak)?

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

Çıktı:

Not 1 2
Ok 2 2

0

İki sözlüğün derin bir karşılaştırmasını yapmanın en kolay yolu (ve daha sağlam olanlarından biri), bunları JSON biçiminde serileştirmek, anahtarları sıralamak ve dize sonuçlarını karşılaştırmaktır:

import json
if json.dumps(x, sort_keys=True) == json.dumps(y, sort_keys=True):
   ... Do something ...

-7
import json

if json.dumps(dict1) == json.dumps(dict2):
    print("Equal")

1
Bu tam olarak istenen şeyi yapmayabilir ve json std lib'i çeker, ancak çalışır ( json.dumpsvarsayılan ayarlarla belirleyici olduğu gibi ).
Daniel Farrell
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.