복붙노트

[PYTHON] 파이썬에서 두 개의 사전 비교하기

PYTHON

파이썬에서 두 개의 사전 비교하기

두 개의 사전이 있지만 단순화를 위해이 두 가지를 사용합니다.

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

이제 x의 각 키, 값 쌍이 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

그리고 튜플이 반환 된 이후에 작동하고 평등을 비교합니다.

내 질문 :

이 올바른지? 이 작업을 수행하는 더 좋은 방법이 있습니까? 더 나은 속도로, 나는 코드 우아함에 대해 이야기하고 있습니다.

업데이트 : 얼마나 많은 키, 값 쌍이 동일한 지 확인해야한다는 것을 잊어 버렸습니다.

해결법

  1. ==============================

    1.두 사전에서 일치하는 값의 수를 알고 싶다면 다음과 같이 말했어 야합니다. :)

    두 사전에서 일치하는 값의 수를 알고 싶다면 다음과 같이 말했어 야합니다. :)

    어쩌면 이런 식으로 :

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

    2.당신이 원하는 것은 단순히 x == y입니다.

    당신이 원하는 것은 단순히 x == y입니다.

    당신이하는 일은 좋은 생각이 아닙니다. 왜냐하면 사전에있는 항목들은 아무런 순서가 없기 때문입니다. [( 'a', 1), ( 'b', 1)]을 [( 'b', 1), ( 'a', 1)] (같은 사전, 다른 순서)와 비교할 수 있습니다.

    예를 들어 다음을 참조하십시오.

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

    차이는 단 하나의 항목이지만 알고리즘은 모든 항목이 다르다는 것을 알게됩니다.

  3. ==============================

    3.

    def dict_compare(d1, d2):
        d1_keys = set(d1.keys())
        d2_keys = set(d2.keys())
        intersect_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 intersect_keys if d1[o] != d2[o]}
        same = set(o for o in intersect_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)
    
  4. ==============================

    4.저는 파이썬에 익숙하지 않지만 @mouad와 비슷한 것을했습니다.

    저는 파이썬에 익숙하지 않지만 @mouad와 비슷한 것을했습니다.

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

    XOR 연산자 (^)는 두 dict에서 모두 동일 할 때 dict의 모든 요소를 ​​제거해야합니다.

  5. ==============================

    5.그냥 사용 :

    그냥 사용 :

    assert cmp(dict1, dict2) == 0
    
  6. ==============================

    6.두 개의 사전에 동일한 내용이 있는지 확인하려면 다음을 사용하십시오.

    두 개의 사전에 동일한 내용이 있는지 확인하려면 다음을 사용하십시오.

    dic1 == dic2
    

    파이썬 워드 프로세서에서 :

    예를 들어, 다음 예제는 모두 { "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
    
  7. ==============================

    7.@mouad의 대답은 두 사전이 단순한 값만 포함한다고 가정하면 좋을 것입니다. 그러나 사전이 포함 된 사전이있는 경우 사전은 해시 가능하지 않으므로 예외가 발생합니다.

    @mouad의 대답은 두 사전이 단순한 값만 포함한다고 가정하면 좋을 것입니다. 그러나 사전이 포함 된 사전이있는 경우 사전은 해시 가능하지 않으므로 예외가 발생합니다.

    내 머리 꼭대기에서 이런 식으로 뭔가를 할 수 있습니다 :

    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(dict2.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
    
  8. ==============================

    8.OP의 마지막 노트까지 또 다른 가능성은 JSON으로 덤프 된 dicts의 해시 (SHA 또는 MD)를 비교하는 것입니다. 해시가 구성되어있는 방법은 동등한 경우 원본 문자열이 동일하다는 것을 보증합니다. 이것은 매우 빠르고 수학적으로 들립니다.

    OP의 마지막 노트까지 또 다른 가능성은 JSON으로 덤프 된 dicts의 해시 (SHA 또는 MD)를 비교하는 것입니다. 해시가 구성되어있는 방법은 동등한 경우 원본 문자열이 동일하다는 것을 보증합니다. 이것은 매우 빠르고 수학적으로 들립니다.

    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))
    
  9. ==============================

    9.deepdiff에 대해 아무도 언급하지 않은 것 같아서, 여기서는 완전성을 위해 추가 할 것입니다. 나는 일반적으로 diff 객체 (중첩 된 객체)를 얻는 것이 매우 편리하다는 것을 알았다.

    deepdiff에 대해 아무도 언급하지 않은 것 같아서, 여기서는 완전성을 위해 추가 할 것입니다. 나는 일반적으로 diff 객체 (중첩 된 객체)를 얻는 것이 매우 편리하다는 것을 알았다.

    import deepdiff
    from pprint import pprint
    
    aa = {
        "a": 1,
        "nested": {
            "b": 1,
        }
    }
    bb = {
        "a": 2,
        "nested": {
            "b": 2,
        }
    }
    pprint(deepdiff.DeepDiff(aa, bb))
    

    산출:

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

    노트:

    그러나, 사전의 차이를 복용, 나는 아주 편리하게 dictdiffer를 찾으십시오.

  10. ==============================

    10.

    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
    
    >>> a = {
        'number': 1,
        'list': ['one', 'two']
    }
    >>> b = {
        'list': ['two', 'one'],
        'number': 1
    }
    >>> equal(a, b)
    True
    
  11. ==============================

    11.두 개의 dict가 키와 값이 같은지 테스트하려면 다음을 수행하십시오.

    두 개의 dict가 키와 값이 같은지 테스트하려면 다음을 수행하십시오.

    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)
    

    다른 값을 반환하려면 다르게 작성하십시오.

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

    즉 두 번 전화해야합니다.

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

    12.이 기능은 명확하고 직관적 인 IMO입니다. 그러나 다만 당신 (다른 사람) 응답을주기 위하여, 여기 나의 것이다 :

    이 기능은 명확하고 직관적 인 IMO입니다. 그러나 다만 당신 (다른 사람) 응답을주기 위하여, 여기 나의 것이다 :

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

    당신이나 다른 누구에게나 유용 할 수 있습니다 ..

  13. ==============================

    13.

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

    다른 옵션이 있습니다.

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

    그래서 당신이 보는 것처럼이 두 ID는 다릅니다. 그러나 부자 비교 연산자는 트릭을하는 것 같습니다 :

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

    14.PyUnit에는 사전을 아름답게 비교하는 방법이 있습니다. 나는 다음의 두 사전을 사용하여 그것을 테스트했고, 당신이 찾고있는 것과 정확히 일치한다.

    PyUnit에는 사전을 아름답게 비교하는 방법이 있습니다. 나는 다음의 두 사전을 사용하여 그것을 테스트했고, 당신이 찾고있는 것과 정확히 일치한다.

    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를 가져 오는 것은 권장하지 않습니다. 제 생각에 PyUnit의 소스는 생산 환경에서 다시 실행될 수 있습니다. 사전을 "예쁜"인쇄하는 pprint를 사용합니다. 이 코드를 "생산 준비"로 변경하는 것은 꽤 쉽습니다.

  15. ==============================

    15.파이썬 3.6에서는 다음과 같이 할 수 있습니다 :

    파이썬 3.6에서는 다음과 같이 할 수 있습니다 :

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

    ret 변수는 dict_1의 모든 항목이 dict_2에있는 경우 참이됩니다.

  16. ==============================

    16.사전보기 객체를 참조하십시오. https://docs.python.org/2/library/stdtypes.html#dict

    사전보기 객체를 참조하십시오. https://docs.python.org/2/library/stdtypes.html#dict

    이 방법으로 dictView1에서 dictView2를 빼면 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')])
    

    이러한 사전보기 객체를 교차, 결합, 차이 (위 그림 참조), 대칭 차이로 연결할 수 있습니다. 보다 나은? 빨리? - 확실하지는 않지만 표준 라이브러리의 일부입니다. 이식성을 위해 큰 이점을줍니다.

  17. ==============================

    17.

    import json
    
    if json.dumps(dict1) == json.dumps(dict2):
        print("Equal")
    
  18. from https://stackoverflow.com/questions/4527942/comparing-two-dictionaries-in-python by cc-by-sa and MIT license