So sánh hai từ điển và kiểm tra có bao nhiêu cặp (khóa, giá trị) bằng nhau


246

Tôi có hai từ điển, nhưng để đơn giản hóa, tôi sẽ lấy hai từ điển này:

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

Bây giờ, tôi muốn so sánh xem mỗi key, valuecặp trong xcó cùng giá trị tương ứng trong y. Vì vậy, tôi đã viết này:

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

Và nó hoạt động kể từ khi tuple được trả lại và sau đó so sánh cho bình đẳng.

Những câu hỏi của tôi:

Điều này có đúng không? Có tốt hơn không cách nào để làm điều này? Tốt hơn không phải ở tốc độ, tôi đang nói về sự thanh lịch của mã.

CẬP NHẬT: Tôi quên đề cập rằng tôi phải kiểm tra xem có bao nhiêu key, valuecặp bằng nhau.



x == y nên đúng. Người ta có thể nhanh chóng kiểm tra REPL. Vui lòng tham khảo: docs.python.org/2/l Library / sttyty.html
Vikrant

Câu trả lời:


179

Nếu bạn muốn biết có bao nhiêu giá trị khớp với cả hai từ điển, bạn nên nói rằng :)

Có lẽ một cái gì đó như thế này:

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

1
Lỗi tương tự nếu có phần tử danh sách cho khóa dict. Tôi nghĩ cmp là cách tốt hơn để làm điều đó trừ khi tôi thiếu bất cứ điều gì.
Đột biến

@Mutant đó là một vấn đề khác. Bạn không thể tạo một từ điển với một listkhóa ở vị trí đầu tiên. x = {[1,2]: 2}sẽ thất bại. Câu hỏi đã có giá trị dicts.
AnnanFay

@annan: sai rồi, câu hỏi chung chung. các ví dụ trong các mô tả câu hỏi có đã "dicts hợp lệ". Nếu tôi đăng một câu hỏi mới, có cùng tiêu đề, nhưng với một câu lệnh "không hợp lệ" khác, ai đó sẽ đánh dấu nó là trùng lặp. Hạ cấp.
ribamar

6
@ribamar câu hỏi là "So sánh hai từ điển [...]". 'Dict không hợp lệ' ở trên với listcác khóa không phải là mã python hợp lệ - các khóa dict phải là bất biến. Do đó, bạn không so sánh từ điển. Nếu bạn thử và sử dụng danh sách làm khóa từ điển, mã của bạn sẽ không chạy. Bạn không có đối tượng để so sánh. Điều này giống như gõ x = dict(23\;dfg&^*$^%$^$%^)sau đó phàn nàn làm thế nào so sánh không hoạt động với từ điển. Tất nhiên nó sẽ không hoạt động. Mặt khác, bình luận của Tim là về khả năng biến đổi values, do đó tôi nói rằng đây là những vấn đề khác nhau.
AnnanFay 17/8/2016

1
@MikeyE - setyêu cầu các giá trị có thể được băm và dictyêu cầu các khóa phải được băm. set(x.keys())sẽ luôn hoạt động vì các khóa được yêu cầu có thể băm, nhưng set(x.values())sẽ thất bại với các giá trị không thể băm được.
Tim Tonomall

173

Những gì bạn muốn làm chỉ đơn giản là x==y

Những gì bạn làm không phải là một ý tưởng tốt, bởi vì các mục trong từ điển không phải là có bất kỳ thứ tự nào. Bạn có thể so sánh [('a',1),('b',1)]với [('b',1), ('a',1)](từ điển giống nhau, thứ tự khác nhau).

Ví dụ, xem điều này:

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

Sự khác biệt chỉ là một mục, nhưng thuật toán của bạn sẽ thấy rằng tất cả các mục đều khác nhau


@ THC4k, xin lỗi vì đã không đề cập. Nhưng tôi phải kiểm tra xem có bao nhiêu giá trị khớp với cả hai từ điển.
user225312

Ok, vậy dựa trên cập nhật của tôi, cách làm của tôi có còn sai không?
user225312

@AA: Tôi đã thêm lý do tại sao bạn không làm việc khi bạn muốn đếm.
Jochen Ritzel

Tôi thấy, nhưng trong trường hợp của tôi cả hai từ điển có cùng độ dài. Và họ sẽ luôn như vậy, vì đó là cách chương trình hoạt động.
user225312

5
Kể từ Python 3.6, dict là thứ tự ra khỏi hộp.
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
Điều này thực sự xử lý các giá trị có thể thay đổi trong dict!
Tim Tonomall

1
Khi tôi chạy cái này, tôi vẫn gặp lỗi khi xử lý các giá trị có thể thay đổi: ValueError: Giá trị thật của DataFrame không rõ ràng. Sử dụng a.empty, a.bool (), a.item (), a.any () hoặc a.all ().
Afflatus

2
@Afflatus - DataFrametheo thiết kế không cho phép so sánh trung thực (trừ khi nó có độ dài bằng 1) khi chúng được thừa hưởng từ đó numpy.ndarray. -credit to stackoverflow.com/a/33307394/994076
Daniel Myers

Đây là một viên ngọc tuyệt đối.
pfabri

125

dic1 == dic2

Từ tài liệu python :

Để minh họa, các ví dụ sau tất cả trở lại một cuốn từ điển bằng để {"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

Việc cung cấp các đối số từ khóa như trong ví dụ đầu tiên chỉ hoạt động đối với các khóa là định danh Python hợp lệ. Nếu không, bất kỳ khóa hợp lệ có thể được sử dụng.

Có giá trị cho cả py2py3.


3
Tôi không đồng ý với @ ErkinAlpGüney. Bạn có thể cung cấp một bằng chứng?
Qi Luo

4
Tôi không đồng ý với @ ErkinAlpGüney. Tài liệu chính thức cho thấy == thực sự so sánh từ điển theo giá trị chứ không phải theo địa chỉ. docs.python.org/2/l Library / stdtypes.html
Matthew Nakayama

3
Hoạt động cho Python 2.7.13
Jesuisme

4
@ankostis:OrderedDict != dict
CONvid19

3
Bạn có thể vui lòng cung cấp đầu vào khi điều này không đúng?
CONvid19

55

Tôi mới làm quen với python nhưng cuối cùng tôi đã làm một cái gì đó tương tự như @mouad

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

Toán tử XOR ( ^) sẽ loại bỏ tất cả các phần tử của dict khi chúng giống nhau trong cả hai dicts.


28
Thật không may, điều này không hoạt động nếu các giá trị trong dict là có thể thay đổi (nghĩa là không thể băm). (Ex {'a':{'b':1}}cho TypeError: unhashable type: 'dict')
Tim Tisdall

54

Vì dường như không ai nhắc đến deepdiff, tôi sẽ thêm nó vào đây cho đầy đủ. Tôi thấy nó rất thuận tiện để nhận khác biệt của các đối tượng (lồng nhau) nói chung:

Cài đặt

pip install deepdiff

Mã mẫu

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

Đầu ra

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

Lưu ý về việc in đẹp kết quả để kiểm tra: Đoạn mã trên hoạt động nếu cả hai ký tự có cùng khóa thuộc tính (với các giá trị thuộc tính có thể khác nhau như trong ví dụ). Tuy nhiên, nếu một "extra"thuộc tính có mặt là một trong những dấu hiệu, thì json.dumps()thất bại với

TypeError: Object of type PrettyOrderedSet is not JSON serializable

Giải pháp: sử dụng diff.to_json()json.loads()/ json.dumps()để in đẹp:

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

Đầu ra:

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

Thay thế: sử dụng pprint, kết quả trong một định dạng khác nhau:

import pprint

# same code as above

pprint.pprint(diff, indent=4)

Đầu ra:

{   '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
Hấp dẫn. Cảm ơn đã trả lời này. Hữu ích cho tôi ít nhất. Câu trả lời này cần nhiều upvote hơn.
Archit Kapoor

46

Chỉ dùng:

assert cmp(dict1, dict2) == 0

6
Dường như nhiệm vụ không chỉ là kiểm tra xem nội dung của cả hai có giống nhau hay không mà còn đưa ra một báo cáo về sự khác biệt
Diego Tercero

29
Tôi tin rằng điều này giống hệt vớidict1 == dict2
Trey Hunner

10
Đối với bất kỳ ai sử dụng Python3.5, phần tích cmphợp đã bị xóa (và nên được xử lý như đã xóa trước đó . Một giải pháp thay thế mà họ đề xuất: (a > b) - (a < b) == cmp(a, b)cho một chức năng tương đương (hoặc tốt hơn __eq____hash__)
nerdwaller

3
@nerdwaller - dicts không phải là loại có thể đặt hàng, vì vậy dict_a> dict_b sẽ đưa ra TypeError:unorderable types: dict() < dict()
Stefano

2
@Stefano: Cuộc gọi tốt, nhận xét của tôi là nhiều hơn để so sánh chung về python (Tôi đã không chú ý đến câu trả lời thực tế, lỗi của tôi).
nerdwaller

9

Câu trả lời của @mouad là tốt nếu bạn cho rằng cả hai từ điển chỉ chứa các giá trị đơn giản. Tuy nhiên, nếu bạn có từ điển có chứa từ điển, bạn sẽ có một ngoại lệ vì từ điển không thể băm được.

Ngoài đỉnh đầu của tôi, một cái gì đó như thế này có thể hoạt động:

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

Nếu bạn sử dụng not isinstance(dict1, dict)thay vì type(dict1) is not dict, điều này sẽ hoạt động trên các lớp khác dựa trên dict. Also, instead of (dict1 [key] == dict2 [key]) , you can do all (atleast_1d (dict1 [key] == dict2 [key])) `để xử lý các mảng ít nhất.
EL_DON

+1, nhưng bạn có thể thoát ra for loopngay khi bạn dicts_are_equaltrở thành sai. Không cần phải tiếp tục nữa.
pfabri

6

Tuy nhiên, một khả năng khác, cho đến ghi chú cuối cùng của OP, là so sánh các giá trị băm ( SHAhoặc MD) của các ký tự được đổ như JSON. Cách băm được xây dựng đảm bảo rằng nếu chúng bằng nhau, các chuỗi nguồn cũng bằng nhau. Điều này là rất nhanh và âm thanh toán học.

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
Điều đó hoàn toàn sai, chỉ cần phân tích dữ liệu vào json là rất chậm. Sau đó băm mà sring lớn mà bạn vừa tạo thậm chí còn tồi tệ hơn. Bạn không bao giờ nên làm điều đó
Bruno

7
@Bruno: trích dẫn OP: "Tốt hơn không phải là tốc độ, tôi đang nói về sự thanh lịch của mã"
WoJ

2
Nó không thanh lịch chút nào, nó cảm thấy không an toàn và nó quá phức tạp cho một vấn đề thực sự đơn giản
Bruno

7
@Bruno: sang trọng là chủ quan. Tôi có thể hiểu rằng bạn không thích nó (và có thể bị đánh giá thấp). Điều này không giống như "sai".
WoJ

4
Đây là một câu trả lời tuyệt vời. json.dumps(d, sort_keys=True)sẽ cung cấp cho bạn JSON chuẩn để bạn có thể chắc chắn rằng cả hai dict đều tương đương nhau. Ngoài ra nó phụ thuộc vào những gì bạn đang cố gắng để đạt được. Ngay khi giá trị không thể JSON hóa, nó sẽ thất bại. Vì vậy, những người nói rằng nó không hiệu quả, hãy xem dự án ujson.
Natim

6

Chức năng IMO tốt, rõ ràng và trực quan. Nhưng chỉ để cho bạn (một câu trả lời) khác, đây là cách của tôi:

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

Có thể hữu ích cho bạn hoặc cho bất cứ ai khác ..

BIÊN TẬP:

Tôi đã tạo một phiên bản đệ quy của một ở trên .. Chưa thấy điều đó trong các câu trả lời khác

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
Hãy cải thiện nó để nó hoạt động cả hai cách. Dòng 2: "cho x1 trong tập hợp (dict1.keys ()). Union (dict2.keys ()):"
nkadwa

Cảm ơn @nkadwa, hiện tại
zwep

5

Để kiểm tra xem hai ký hiệu có bằng nhau về khóa và giá trị không:

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)

Nếu bạn muốn trả về các giá trị khác nhau, hãy viết nó khác nhau:

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

Bạn sẽ phải gọi nó hai lần tức là

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

3

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

Kiểm tra

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

3

Một so sánh đơn giản với == nên là đủ ngày nay (python 3.8). Ngay cả khi bạn so sánh các ký tự tương tự theo một thứ tự khác (ví dụ cuối cùng). Điều tốt nhất là, bạn không cần gói bên thứ ba để thực hiện việc này.

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

Bị trễ trong phản ứng của tôi là tốt hơn bao giờ hết!

So sánh Not_Equal hiệu quả hơn so với Equal. Vì hai dicts như vậy không bằng nhau nếu không tìm thấy bất kỳ giá trị quan trọng nào trong một dict trong dict kia. Mã dưới đây xem xét rằng bạn có thể so sánh dict mặc định và do đó sử dụng get thay vì getitem [].

Sử dụng một loại giá trị ngẫu nhiên làm mặc định trong lệnh gọi bằng với khóa được truy xuất - chỉ trong trường hợp các ký tự có giá trị Không là một trong một lệnh và khóa đó không tồn tại trong khóa kia. Ngoài ra, điều kiện get! = Được kiểm tra trước điều kiện không có hiệu quả vì bạn đang thực hiện kiểm tra các khóa và giá trị từ cả hai phía cùng một lúc.

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

Tôi đang sử dụng giải pháp này hoạt động hoàn hảo cho tôi trong 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

Nó so sánh dict, list và bất kỳ loại nào khác tự thực hiện toán tử "==". Nếu bạn cần so sánh một cái gì đó khác, bạn cần thêm một nhánh mới trong "nếu cây".

Mong rằng sẽ giúp.


2

cho python3:

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'

Đây là một lựa chọn khác:

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

Vì vậy, như bạn thấy hai id là khác nhau. Nhưng các toán tử so sánh phong phú dường như thực hiện các mẹo:

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

Trong PyUnit có một phương pháp so sánh từ điển rất hay. Tôi đã thử nghiệm nó bằng cách sử dụng hai từ điển sau đây và nó thực hiện chính xác những gì bạn đang tìm kiếm.

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

Tôi không khuyên bạn nên nhập unittestvào mã sản xuất của bạn. Tôi nghĩ rằng nguồn trong PyUnit có thể được sử dụng lại để chạy trong sản xuất. Nó sử dụng pprint"bản in đẹp" từ điển. Có vẻ khá dễ dàng để điều chỉnh mã này để "sẵn sàng sản xuất".


1

xem các đối tượng xem từ điển: https://docs.python.org/2/l Library / stdtypes.html#dict

Bằng cách này, bạn có thể trừ dictView2 khỏi dictView1 và nó sẽ trả về một tập hợp các cặp khóa / giá trị khác nhau trong 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')])

Bạn có thể giao nhau, hợp nhất, khác biệt (hiển thị ở trên), khác biệt đối xứng các đối tượng xem từ điển này.
Tốt hơn? Nhanh hơn? - không chắc chắn, nhưng là một phần của thư viện tiêu chuẩn - điều này làm cho nó trở thành một điểm cộng lớn cho tính di động


1

Mã dưới đây sẽ giúp bạn so sánh danh sách dict trong 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

3
Chào mừng bạn đến với Stack Overflow! Mặc dù đoạn mã này có thể giải quyết câu hỏi, bao gồm một lời giải thích thực sự giúp cải thiện chất lượng bài đăng của bạn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho độc giả trong tương lai và những người đó có thể không biết lý do cho đề xuất mã của bạn. Xin vui lòng cố gắng không làm đông mã của bạn với các bình luận giải thích, điều này làm giảm khả năng đọc của cả mã và các giải thích!
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

Trong Python 3.6, nó có thể được thực hiện như sau: -

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

biến ret sẽ là true nếu tất cả các mục của dict_1 hiện tại trong dict_2


0

Đây là câu trả lời của tôi, sử dụng một cách đệ quy:

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)

Mong rằng sẽ giúp!


0

Tại sao không chỉ lặp qua một từ điển và kiểm tra cái khác trong quy trình (giả sử cả hai từ điển có cùng khóa)?

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

Đầu ra:

Not 1 2
Ok 2 2

-7
import json

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

1
Điều này có thể không làm những gì được yêu cầu chính xác và kéo theo json std lib, nhưng nó hoạt động (như json.dumpslà xác định với các cài đặt mặc định).
Daniel Farrell
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.