Reputation: 501
I am trying to go through all elements of two given dictionaries to make sure they are equal, and if not I want the name of the property where they differ.
Here is my basic approach:
# Dictionnaries
v1 = { "a" : { "b" : 1, "c" : 2 }, "d" : { "e" : { "f" : 3 }}}
v2 = { "a" : { "b" : 1, "c" : 2 }, "d" : { "e" : { "f" : 4 }}}
def gen(k, v):
if type(v) is dict:
for k in v:
yield from gen(k, v[k])
else:
yield k, v
# Used alone the generator works as expected:
for k, v in gen("root", v1):
print("{}: {}".format(k, v))
My problem is that I want to compare the two dictionaries, from what I could gather it should look like this:
for k1, v1, k2, v2 in zip(gen("root1", v1), gen("root2", v2)):
print("{}: {}".format(k1, v1))
print("{}: {}".format(k2, v2))
print("===========")
The interpreter says only two values are returned, so I assumed this would work (and it does):
for t1, t2 in zip(gen("root1", v1), gen("root2", v2)):
print("{}: {}".format(t1[0], t1[1]))
print("{}: {}".format(t2[0], t2[1]))
print("===========")
It might be purely preferential, but I really wonder
*
, but no success. Why can't I do zip(*gen(...), *gen(...))
?(By the way I know I could just add k1, v1, k2, v2 = *t1, *t2
at the beginning of the loop, I'm just looking for a nicer solution)
Upvotes: 2
Views: 265
Reputation: 139
Your question was more specific to syntax, but there are some things you might want to consider:
If you want to visually compare dicts, here is a solution that takes care of these issues.
Assumption: structure of the dicts is the same (keys are the same, if a value for 1 is a dict, it will be a dict for the other one, those keys can't be iterables of other types, e.g. lists).
from collections import deque
def gen(dct1, dct2):
q = deque()
q.append(("root", dct1, dct2))
while q:
k, d1, d2 = q.pop()
for key in d1: # assuming the same keys for both dicts
val1 = d1[key]
val2 = d2[key]
# assuming that if the structure is the same -> if val1 is a dict, val2 is a dict as well
if isinstance(val1, dict):
q.append((k, val1, val2))
else:
yield key, val1, val2
for k, val1, val2 in gen(v1, v2):
print("{}: {}".format(k, val1))
print("{}: {}".format(k, val2))
print("===========")
Upvotes: 0
Reputation: 684
You can unpack each returned tuple as follows:
for (k1, val1), (k2, val2) in zip(gen('root1', v1), gen('root2', v2)):
...
Upvotes: 4