Unterschiede zwischen zwei Datenstrukturen

08/08/2010 - 20:28 von Florian Weimer | Report spam
Ich habe zwei geschachtelte Datenstrukturen (in erster Linie mit
Typen, die sich ggf. auch mit JSON ausdrücken ließen) und hàtte nun
gerne eine halbwegs lesbare Übersicht über die Unterschiede. Gibt es
dafür etwas Fertiges?
 

Lesen sie die antworten

#1 Peter Otten
08/08/2010 - 23:03 | Warnen spam
Florian Weimer wrote:

Ich habe zwei geschachtelte Datenstrukturen (in erster Linie mit
Typen, die sich ggf. auch mit JSON ausdrücken ließen) und hàtte nun
gerne eine halbwegs lesbare Übersicht über die Unterschiede. Gibt es
dafür etwas Fertiges?



Eher halbfertig, aber vielleicht làsst sich was draus machen:

differs = {}

def register(*pairs):
def deco(f):
for p in pairs:
if not isinstance(p, tuple):
p = p, p
differs[p] = f
return f
return deco

@register(int, str)
def atomic_differ(context, a, b, name):
if a == b:
yield name, "equal"
else:
yield name, "modified (%r --> %r)" % (a, b)

class Context(object):
def __init__(self):
self.level = -1
def indent(self):
self.level += 1
def dedent(self):
self.level -= 1
def make_differ(self, a, b, key):
d = differs.get((a.__class__, b.__class__), default_differ)
return d(self, a, b, key)

@register(dict)
def dict_differ(context, a, b, name):
yield name
context.indent()
left = set(a)
right = set(b)
all = sorted(left | right)
both = left & right
for key in all:
if key in both:
for item in context.make_differ(a[key], b[key], key):
yield item
elif key in left:
yield key, "removed"
else:
yield key, "added"
context.dedent()

def default_differ(context, a, b, name):
if a == b:
yield name, "equal"
else:
for item in dict_differ(context, a.__dict__, b.__dict__, name):
yield item

def diff(context, a, b):
differ = differs.get((a.__class__, b.__class__), default_differ)
d = differ(context, a, b, "#main")
next(d)
return d

def main():
context = Context()
class A(object):
def __init__(self, **kw):
self.__dict__.update(kw)
a = {
"a": {1: "x", 2: "z"},
"b": 42,
"c": "foo",
"d": "whatever",
"x": A(a=A(alpha=2, beta=2), b=dict(one=1, two=2, three=3), cB),
"y": 12
}
b = {
"a": {1: "y"},
"b": 43,
"c": "foo",
"e": "bar",
"x": A(a=A(alpha=1, beta=2), b=dict(one=1, two=3, four=4)),
"y": 12,
"z": 13,
}

for item in diff(context, a, b):
if isinstance(item, tuple):
item = "%s: %s" % item
print context.level*" " + item

if __name__ == "__main__":
main()

Peter

Ähnliche fragen