2つのPython辞書に含まれるキーの違いを計算する


171

2つのPython辞書- dictAとがあるとしdictBます。私は中に存在する任意のキーがあるかどうかを確認する必要があるdictBではありませんがdictA。それについて行く最も速い方法は何ですか?

辞書のキーをセットに変換してから始めましょうか?

あなたの考えを知ることに興味があります...


ご回答ありがとうございます。

私の質問を適切に述べなかったことに対する謝罪。私のシナリオはこのようなものです-とdictA同じであるdictBか、いくつかのキーが欠落しているdictB可能性があります。そうでない場合、いくつかのキーの値が異なるため、dictAます。

問題は、辞書に標準がなく、dictの口述になり得る値を持つ可能性があることです。

いう

dictA={'key1':a, 'key2':b, 'key3':{'key11':cc, 'key12':dd}, 'key4':{'key111':{....}}}
dictB={'key1':a, 'key2:':newb, 'key3':{'key11':cc, 'key12':newdd, 'key13':ee}.......

したがって、「key2」の値を新しい値にリセットし、「key13」を辞書内に追加する必要があります。キー値の形式は固定されていません。単純な値でも、dictでも、dict of dictでもかまいません。

回答:


234

キーに対して集合演算を使用できます。

diff = set(dictb.keys()) - set(dicta.keys())

追加されたもの、削除されたもの、同じキーと値のペア、変更されたキーと値のペアをすべて見つけるためのクラスを次に示します。

class DictDiffer(object):
    """
    Calculate the difference between two dictionaries as:
    (1) items added
    (2) items removed
    (3) keys same in both but changed values
    (4) keys same in both and unchanged values
    """
    def __init__(self, current_dict, past_dict):
        self.current_dict, self.past_dict = current_dict, past_dict
        self.set_current, self.set_past = set(current_dict.keys()), set(past_dict.keys())
        self.intersect = self.set_current.intersection(self.set_past)
    def added(self):
        return self.set_current - self.intersect 
    def removed(self):
        return self.set_past - self.intersect 
    def changed(self):
        return set(o for o in self.intersect if self.past_dict[o] != self.current_dict[o])
    def unchanged(self):
        return set(o for o in self.intersect if self.past_dict[o] == self.current_dict[o])

次に出力例を示します。

>>> a = {'a': 1, 'b': 1, 'c': 0}
>>> b = {'a': 1, 'b': 2, 'd': 0}
>>> d = DictDiffer(b, a)
>>> print "Added:", d.added()
Added: set(['d'])
>>> print "Removed:", d.removed()
Removed: set(['c'])
>>> print "Changed:", d.changed()
Changed: set(['b'])
>>> print "Unchanged:", d.unchanged()
Unchanged: set(['a'])

githubリポジトリとして利用可能:https : //github.com/hughdbrown/dictdiffer


3
スマートソリューション、ありがとう!変更された値または変更されていない値がdictインスタンスであるかどうかを確認し、再帰関数を呼び出してクラスを使用してそれらを再度確認することにより、ネストされたdictで動作するようにしました。
AJJ

1
@AJJその実装を見たいです。
urschrei 2013年

1
def update(self, new_dict): self.__init__(new_dict, self.current_dict)ローリング比較を実行できるように、などはどうですか
ニックT

いくつかの注意:DictDifferクラスはステートレスクラスであり、関数である可能性があります。changedそしてunchanged値は同じループで計算することができます。この2つの関数は、のlist代わりにを返す可能性がsetあります。詳細な比較については、ユニットテストフレームワークdocs.python.org/2/library/unittest.htmlをご覧くださいassertDictEqual。ソースコードのメソッドに従ってください。
Laurent LAPORTE 2013年

1
FWIW、set(dictb)おそらくより良いですset(dictb.keys())
mgilson 2014年

60

違いを再帰的に知りたい場合のために、私はpython用のパッケージを作成しました:https : //github.com/seperman/deepdiff

取り付け

PyPiからインストール:

pip install deepdiff

使用例

インポート

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

同じオブジェクトが空を返す

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

アイテムの種類が変更されました

>>> t1 = {1:1, 2:2, 3:3}
>>> t2 = {1:1, 2:"2", 3:3}
>>> pprint(DeepDiff(t1, t2), indent=2)
{ 'type_changes': { 'root[2]': { 'newtype': <class 'str'>,
                                 'newvalue': '2',
                                 'oldtype': <class 'int'>,
                                 'oldvalue': 2}}}

アイテムの値が変更されました

>>> t1 = {1:1, 2:2, 3:3}
>>> t2 = {1:1, 2:4, 3:3}
>>> pprint(DeepDiff(t1, t2), indent=2)
{'values_changed': {'root[2]': {'newvalue': 4, 'oldvalue': 2}}}

追加または削除されたアイテム

>>> t1 = {1:1, 2:2, 3:3, 4:4}
>>> t2 = {1:1, 2:4, 3:3, 5:5, 6:6}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff)
{'dic_item_added': ['root[5]', 'root[6]'],
 'dic_item_removed': ['root[4]'],
 'values_changed': {'root[2]': {'newvalue': 4, 'oldvalue': 2}}}

文字列の違い

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":"world"}}
>>> t2 = {1:1, 2:4, 3:3, 4:{"a":"hello", "b":"world!"}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff, indent = 2)
{ 'values_changed': { 'root[2]': {'newvalue': 4, 'oldvalue': 2},
                      "root[4]['b']": { 'newvalue': 'world!',
                                        'oldvalue': 'world'}}}

文字列の違い2

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":"world!\nGoodbye!\n1\n2\nEnd"}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":"world\n1\n2\nEnd"}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff, indent = 2)
{ 'values_changed': { "root[4]['b']": { 'diff': '--- \n'
                                                '+++ \n'
                                                '@@ -1,5 +1,4 @@\n'
                                                '-world!\n'
                                                '-Goodbye!\n'
                                                '+world\n'
                                                ' 1\n'
                                                ' 2\n'
                                                ' End',
                                        'newvalue': 'world\n1\n2\nEnd',
                                        'oldvalue': 'world!\n'
                                                    'Goodbye!\n'
                                                    '1\n'
                                                    '2\n'
                                                    'End'}}}

>>> 
>>> print (ddiff['values_changed']["root[4]['b']"]["diff"])
--- 
+++ 
@@ -1,5 +1,4 @@
-world!
-Goodbye!
+world
 1
 2
 End

タイプ変更

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, 3]}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":"world\n\n\nEnd"}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff, indent = 2)
{ 'type_changes': { "root[4]['b']": { 'newtype': <class 'str'>,
                                      'newvalue': 'world\n\n\nEnd',
                                      'oldtype': <class 'list'>,
                                      'oldvalue': [1, 2, 3]}}}

リストの違い

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, 3, 4]}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2]}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff, indent = 2)
{'iterable_item_removed': {"root[4]['b'][2]": 3, "root[4]['b'][3]": 4}}

リストの違い2:

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, 3]}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 3, 2, 3]}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff, indent = 2)
{ 'iterable_item_added': {"root[4]['b'][3]": 3},
  'values_changed': { "root[4]['b'][1]": {'newvalue': 3, 'oldvalue': 2},
                      "root[4]['b'][2]": {'newvalue': 2, 'oldvalue': 3}}}

順序や重複を無視して違いをリストする:(上記と同じ辞書で)

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, 3]}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 3, 2, 3]}}
>>> ddiff = DeepDiff(t1, t2, ignore_order=True)
>>> print (ddiff)
{}

辞書を含むリスト:

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, {1:1, 2:2}]}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, {1:3}]}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff, indent = 2)
{ 'dic_item_removed': ["root[4]['b'][2][2]"],
  'values_changed': {"root[4]['b'][2][1]": {'newvalue': 3, 'oldvalue': 1}}}

セット:

>>> t1 = {1, 2, 8}
>>> t2 = {1, 2, 3, 5}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (DeepDiff(t1, t2))
{'set_item_added': ['root[3]', 'root[5]'], 'set_item_removed': ['root[8]']}

名前付きタプル:

>>> from collections import namedtuple
>>> Point = namedtuple('Point', ['x', 'y'])
>>> t1 = Point(x=11, y=22)
>>> t2 = Point(x=11, y=23)
>>> pprint (DeepDiff(t1, t2))
{'values_changed': {'root.y': {'newvalue': 23, 'oldvalue': 22}}}

カスタムオブジェクト:

>>> class ClassA(object):
...     a = 1
...     def __init__(self, b):
...         self.b = b
... 
>>> t1 = ClassA(1)
>>> t2 = ClassA(2)
>>> 
>>> pprint(DeepDiff(t1, t2))
{'values_changed': {'root.b': {'newvalue': 2, 'oldvalue': 1}}}

追加されたオブジェクト属性:

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

これありがとう!私のプロジェクトに実装しただけで、うまくいきます!
gtalarico 2016年

1
@gtalaricoお役に立ててうれしいです!親切な言葉をありがとう!
Seperman、2016年

リストの順序の違いを無視するオプションはありますか?私のアプリケーションはそれを気にしないので。
レイヤン

素晴らしいプロジェクトで、私の側からの最小限の努力ですべての仕事をしました。ありがとう!
Stanislav Tsepa

@LeiYangはい、設定できますignore_order=True。あなたはドキュメントを見つけることができます deepdiff.readthedocs.io
en / latest /

18

その「速い」かどうかはわかりませんが、通常はこれを行うことができます

dicta = {"a":1,"b":2,"c":3,"d":4}
dictb = {"a":1,"d":2}
for key in dicta.keys():
    if not key in dictb:
        print key

あなたは交換する必要がdictaありdictb、彼はそれらのキーdictbがにないことを知りたいのでdicta
ガンボ

2
for key in dicta.keys():=>for key in dicta:
ジャン=フランソワ・ファーブル

15

Alex Martelliが書いたように、単にBのキーがAにないかどうかを確認したい場合は、 any(True for k in dictB if k not in dictA)その方法です。

不足しているキーを見つけるには:

diff = set(dictB)-set(dictA) #sets

C:\Dokumente und Einstellungen\thc>python -m timeit -s "dictA =    
dict(zip(range(1000),range
(1000))); dictB = dict(zip(range(0,2000,2),range(1000)))" "diff=set(dictB)-set(dictA)"
10000 loops, best of 3: 107 usec per loop

diff = [ k for k in dictB if k not in dictA ] #lc

C:\Dokumente und Einstellungen\thc>python -m timeit -s "dictA = 
dict(zip(range(1000),range
(1000))); dictB = dict(zip(range(0,2000,2),range(1000)))" "diff=[ k for k in dictB if
k not in dictA ]"
10000 loops, best of 3: 95.9 usec per loop

したがって、これら2つのソリューションはほぼ同じ速度です。


8
これはより理にかなっています:any(k not in dictA for k in dictB)
hughdbrown、2011年

13

あなたが本当に言っていることを本当に意味している場合(AではなくBに「キーがある」場合にのみ検索する必要があり、どれが存在するかはわからない)、最も速い方法は次のとおりです。

if any(True for k in dictB if k not in dictA): ...

「もし」がAではなくBにあり、「IF」だけでなく、そのようなキーがある場合、実際に見つける必要がある場合は、既存の回答が非常に適切です(ただし、それが将来の質問でより正確になることをお勧めします)本当にあなたが何を意味するか;-)。



8

hughdbrownによる一番上の答えは集合差の使用を提案しており、これは間違いなく最良のアプローチです。

diff = set(dictb.keys()) - set(dicta.keys())

このコードの問題は、2つのセットを作成するためだけに2つのリストを作成するため、4Nの時間と2Nのスペースを浪費することです。また、必要以上に複雑になります。

通常、これは大したことではありませんが、そうであれば:

diff = dictb.keys() - dicta

Python 2

Python 2では、keys()ではなく、キーのリストを返しますKeysView。ですから、viewkeys()直接依頼する必要があります。

diff = dictb.viewkeys() - dicta

デュアルバージョン2.7 / 3.xコードの場合、うまくいけば、sixまたは同様の何かを使用しているので、以下を使用できますsix.viewkeys(dictb)

diff = six.viewkeys(dictb) - dicta

2.4-2.6では、はありませんKeysView。ただし、リストを最初に作成する代わりに、イテレータから直接左セットを作成することで、少なくとも4NからNにコストを削減できます。

diff = set(dictb) - dicta

アイテム

私はdictBと同じであるdictAを持っているか、dictBと比較していくつかのキーが欠落している可能性があります。そうでない場合、一部のキーの値が異なる可能性があります。

したがって、実際にはキーを比較する必要はありませんが、アイテムを比較する必要があります。値が文字列のようにハッシュ可能でItemsViewあるSet場合のみ、An はa です。もしそうなら、それは簡単です:

diff = dictb.items() - dicta.items()

再帰的な差分

質問は再帰的なdiffを直接求めているわけではありませんが、値の例の一部はdictであり、期待される出力は再帰的にそれらを比較しているようです。これを行う方法を示す複数の回答がすでにここにあります。



@Jean-FrançoisFabreもちろん、Python 2.4-2.6のものは2018年にはすでにかなり無関係です…
abarnert

一部の人は2.6で立ち往生している
ジャン=フランソワ・ファーブル


3

これが機能する方法であり、キーがに評価されFalse、ジェネレータ式を使用して、可能であれば早期にフォールアウトします。しかし、それは例外的にきれいではありません。

any(map(lambda x: True, (k for k in b if k not in a)))

編集:

THC4kは私のコメントに対する別の回答への返信を投稿しました。以下は、上記を行うためのより良い、よりきれいな方法です。

any(True for k in b if k not in a)

どうしてそれが私の心を超えたことがないのかわからない...


これは、以前のアレックスマルテッリの答えと同じ答えである
ジャン=フランソワ・ファーブル

今です。私がそれを投稿したとき(9年前、笑)、以前の答えはany(k for k in dictB if k not in dictA)同じではありませんでした(誤ったキーの場合)。編集履歴/タイムスタンプを確認してください。
スティーブロス2018年

3

これは古い質問であり、私が必要とするものよりも少しだけ尋ねるので、この答えは実際にこの質問が尋ねる以上に解決します。この質問の回答は、次のことを解決するのに役立ちました。

  1. (質問)2つの辞書の違いを記録する
  2. #1との違いをベースディクショナリにマージする
  3. (質問)2つの辞書の違いをマージします(dictionary#2をdiff辞書であるかのように扱います)
  4. アイテムの移動や変更を検出してみてください
  5. (尋ねられた)これをすべて再帰的に行う

これらすべてをJSONと組み合わせると、非常に強力な構成ストレージのサポートが実現します。

解決策(github上でも):

from collections import OrderedDict
from pprint import pprint


class izipDestinationMatching(object):
    __slots__ = ("attr", "value", "index")

    def __init__(self, attr, value, index):
        self.attr, self.value, self.index = attr, value, index

    def __repr__(self):
        return "izip_destination_matching: found match by '%s' = '%s' @ %d" % (self.attr, self.value, self.index)


def izip_destination(a, b, attrs, addMarker=True):
    """
    Returns zipped lists, but final size is equal to b with (if shorter) a padded with nulls
    Additionally also tries to find item reallocations by searching child dicts (if they are dicts) for attribute, listed in attrs)
    When addMarker == False (patching), final size will be the longer of a, b
    """
    for idx, item in enumerate(b):
        try:
            attr = next((x for x in attrs if x in item), None)  # See if the item has any of the ID attributes
            match, matchIdx = next(((orgItm, idx) for idx, orgItm in enumerate(a) if attr in orgItm and orgItm[attr] == item[attr]), (None, None)) if attr else (None, None)
            if match and matchIdx != idx and addMarker: item[izipDestinationMatching] = izipDestinationMatching(attr, item[attr], matchIdx)
        except:
            match = None
        yield (match if match else a[idx] if len(a) > idx else None), item
    if not addMarker and len(a) > len(b):
        for item in a[len(b) - len(a):]:
            yield item, item


def dictdiff(a, b, searchAttrs=[]):
    """
    returns a dictionary which represents difference from a to b
    the return dict is as short as possible:
      equal items are removed
      added / changed items are listed
      removed items are listed with value=None
    Also processes list values where the resulting list size will match that of b.
    It can also search said list items (that are dicts) for identity values to detect changed positions.
      In case such identity value is found, it is kept so that it can be re-found during the merge phase
    @param a: original dict
    @param b: new dict
    @param searchAttrs: list of strings (keys to search for in sub-dicts)
    @return: dict / list / whatever input is
    """
    if not (isinstance(a, dict) and isinstance(b, dict)):
        if isinstance(a, list) and isinstance(b, list):
            return [dictdiff(v1, v2, searchAttrs) for v1, v2 in izip_destination(a, b, searchAttrs)]
        return b
    res = OrderedDict()
    if izipDestinationMatching in b:
        keepKey = b[izipDestinationMatching].attr
        del b[izipDestinationMatching]
    else:
        keepKey = izipDestinationMatching
    for key in sorted(set(a.keys() + b.keys())):
        v1 = a.get(key, None)
        v2 = b.get(key, None)
        if keepKey == key or v1 != v2: res[key] = dictdiff(v1, v2, searchAttrs)
    if len(res) <= 1: res = dict(res)  # This is only here for pretty print (OrderedDict doesn't pprint nicely)
    return res


def dictmerge(a, b, searchAttrs=[]):
    """
    Returns a dictionary which merges differences recorded in b to base dictionary a
    Also processes list values where the resulting list size will match that of a
    It can also search said list items (that are dicts) for identity values to detect changed positions
    @param a: original dict
    @param b: diff dict to patch into a
    @param searchAttrs: list of strings (keys to search for in sub-dicts)
    @return: dict / list / whatever input is
    """
    if not (isinstance(a, dict) and isinstance(b, dict)):
        if isinstance(a, list) and isinstance(b, list):
            return [dictmerge(v1, v2, searchAttrs) for v1, v2 in izip_destination(a, b, searchAttrs, False)]
        return b
    res = OrderedDict()
    for key in sorted(set(a.keys() + b.keys())):
        v1 = a.get(key, None)
        v2 = b.get(key, None)
        #print "processing", key, v1, v2, key not in b, dictmerge(v1, v2)
        if v2 is not None: res[key] = dictmerge(v1, v2, searchAttrs)
        elif key not in b: res[key] = v1
    if len(res) <= 1: res = dict(res)  # This is only here for pretty print (OrderedDict doesn't pprint nicely)
    return res

2

標準についてはどうですか(FULLオブジェクトと比較)

PyDev->新しいPyDevモジュール->モジュール:unittest

import unittest


class Test(unittest.TestCase):


    def testName(self):
        obj1 = {1:1, 2:2}
        obj2 = {1:1, 2:2}
        self.maxDiff = None # sometimes is usefull
        self.assertDictEqual(d1, d2)

if __name__ == "__main__":
    #import sys;sys.argv = ['', 'Test.testName']

    unittest.main()

ネストされた巨大な辞書があり、内部のすべてのものを比較して違いを確認したい場合、これは素晴らしいことです。ありがとう!
Matthew Moisen 2017

2

Python≥2.7の場合:

# update different values in dictB
# I would assume only dictA should be updated,
# but the question specifies otherwise

for k in dictA.viewkeys() & dictB.viewkeys():
    if dictA[k] != dictB[k]:
        dictB[k]= dictA[k]

# add missing keys to dictA

dictA.update( (k,dictB[k]) for k in dictB.viewkeys() - dictA.viewkeys() )

1

2つの辞書キーを詳細に比較するためのソリューションを次に示します。

def compareDictKeys(dict1, dict2):
  if type(dict1) != dict or type(dict2) != dict:
      return False

  keys1, keys2 = dict1.keys(), dict2.keys()
  diff = set(keys1) - set(keys2) or set(keys2) - set(keys1)

  if not diff:
      for key in keys1:
          if (type(dict1[key]) == dict or type(dict2[key]) == dict) and not compareDictKeys(dict1[key], dict2[key]):
              diff = True
              break

  return not diff

1

3つ以上の辞書を比較できるソリューションは次のとおりです。

def diff_dict(dicts, default=None):
    diff_dict = {}
    # add 'list()' around 'd.keys()' for python 3 compatibility
    for k in set(sum([d.keys() for d in dicts], [])):
        # we can just use "values = [d.get(k, default) ..." below if 
        # we don't care that d1[k]=default and d2[k]=missing will
        # be treated as equal
        if any(k not in d for d in dicts):
            diff_dict[k] = [d.get(k, default) for d in dicts]
        else:
            values = [d[k] for d in dicts]
            if any(v != values[0] for v in values):
                diff_dict[k] = values
    return diff_dict

使用例:

import matplotlib.pyplot as plt
diff_dict([plt.rcParams, plt.rcParamsDefault, plt.matplotlib.rcParamsOrig])

1

2つの辞書の対称的な違いの私のレシピ:

def find_dict_diffs(dict1, dict2):
    unequal_keys = []
    unequal_keys.extend(set(dict1.keys()).symmetric_difference(set(dict2.keys())))
    for k in dict1.keys():
        if dict1.get(k, 'N\A') != dict2.get(k, 'N\A'):
            unequal_keys.append(k)
    if unequal_keys:
        print 'param', 'dict1\t', 'dict2'
        for k in set(unequal_keys):
            print str(k)+'\t'+dict1.get(k, 'N\A')+'\t '+dict2.get(k, 'N\A')
    else:
        print 'Dicts are equal'

dict1 = {1:'a', 2:'b', 3:'c', 4:'d', 5:'e'}
dict2 = {1:'b', 2:'a', 3:'c', 4:'d', 6:'f'}

find_dict_diffs(dict1, dict2)

そして結果は:

param   dict1   dict2
1       a       b
2       b       a
5       e       N\A
6       N\A     f

1

他の回答で述べたように、unittestは辞書を比較するための優れた出力を生成しますが、この例では、最初にテスト全体を作成する必要はありません。

単体テストのソースをこする、これだけで公正な解決策を得ることができるようです:

import difflib
import pprint

def diff_dicts(a, b):
    if a == b:
        return ''
    return '\n'.join(
        difflib.ndiff(pprint.pformat(a, width=30).splitlines(),
                      pprint.pformat(b, width=30).splitlines())
    )

そう

dictA = dict(zip(range(7), map(ord, 'python')))
dictB = {0: 112, 1: 'spam', 2: [1,2,3], 3: 104, 4: 111}
print diff_dicts(dictA, dictB)

結果:

{0: 112,
-  1: 121,
-  2: 116,
+  1: 'spam',
+  2: [1, 2, 3],
   3: 104,
-  4: 111,
?        ^

+  4: 111}
?        ^

-  5: 110}

どこ:

  • '-'は、最初の辞書ではなく最初の辞書のキー/値を示します
  • '+'は2番目のキー/値を示しますが、最初のディクショナリは示しません

unittestと同様に、唯一の注意点は、末尾のコンマ/ブラケットが原因で、最終的なマッピングが差分であると考えることができるということです。


1

@Maxxには素晴らしい答えがあります。Pythonがunittest提供するツールを使用してください。

import unittest


class Test(unittest.TestCase):
    def runTest(self):
        pass

    def testDict(self, d1, d2, maxDiff=None):
        self.maxDiff = maxDiff
        self.assertDictEqual(d1, d2)

次に、コード内のどこでも呼び出すことができます。

try:
    Test().testDict(dict1, dict2)
except Exception, e:
    print e

結果の出力は、からの出力のようになり、異なる各行でdiff辞書をプリティプリント+または-プリペンドします。


0

それでもまだ関連があるかどうかはわかりませんが、この問題に遭遇しました。私の状況では、ネストされたすべての辞書などの変更の辞書を返す必要がありました。良い解決策を見つけることができませんでしたが、単純な関数を作成してしまいましたこれを行うには。お役に立てれば、


2
リンクの代わりに、OPの問題を実際に解決するコードを最小限にして、回答に含めることをお勧めします。リンクが切れたり移動したりすると、答えが役に立たなくなります。
ジョージストッカー2013年

0

任意のdict構造との完全な比較のための組み込みソリューションが必要な場合は、@ Maxxの答えが適切な出発点です。

import unittest

test = unittest.TestCase()
test.assertEqual(dictA, dictB)

そのようなテストクラスをインスタンス化することはできません。
Ben Liyanage、2015年

0

ghostdog74の答えに基づいて、

dicta = {"a":1,"d":2}
dictb = {"a":5,"d":2}

for value in dicta.values():
    if not value in dictb.values():
        print value

dictaの異なる値を出力します


0

これを試して、両方の辞書にあるキーの交差を見つけます。2番目の辞書にないキーが必要な場合は、not in ...

intersect = filter(lambda x, dictB=dictB.keys(): x in dictB, dictA.keys())
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.