2016-05-24 10 views
1

Für einige Nachbearbeitung, ich brauche wie dieseeine verschachtelte dict Struktur in einem Datensatz

{'foo': { 
      'cat': {'name': 'Hodor', 'age': 7}, 
      'dog': {'name': 'Mordor', 'age': 5}}, 
'bar': { 'rat': {'name': 'Izidor', 'age': 3}} 
} 

in diesem Datensatz eine Struktur zu glätten:

[{'foobar': 'foo', 'animal': 'dog', 'name': 'Mordor', 'age': 5}, 
{'foobar': 'foo', 'animal': 'cat', 'name': 'Hodor', 'age': 7}, 
{'foobar': 'bar', 'animal': 'rat', 'name': 'Izidor', 'age': 3}] 

Also schrieb ich diese Funktion:

Ich war nicht wirklich zufrieden, weil ich copy.copy verwenden muss, um meine Eingänge zu schützen. Bei der Verwendung von flatten möchte man natürlich nicht, dass die Eingänge geändert werden.

Dann habe ich über eine Alternative nachgedacht, die mehr globale Variablen verwendet (zumindest global zu flatten) und einen Index anstelle von primary_keys zu visit direkt verwendet. Allerdings bedeutet dies nicht wirklich mir helfen, loszuwerden, die hässlichen ursprüngliche Kopie zu erhalten:

keys = copy.copy(primary_keys) 
    keys.reverse() 

So, hier ist meine letzte Version:

def flatten(data, keys): 
    data = copy.copy(data) 
    keys = copy.copy(keys) 
    keys.reverse() 
    out = [] 
    values = {} 
    def visit(node, id): 
     if id: 
      id -= 1 
      for key, child in node.iteritems(): 
       values[keys[id]] = key 
       visit(child, id) 
     else: 
      node.update(values) 
      out.append(node) 
    visit(data, len(keys)) 
    return out  

Gibt es eine bessere Implementierung (das kann die Verwendung von vermeiden copy.copy)?

Antwort

1

Bearbeiten: geändert, um die Tiefe des variablen Wörterbuchs zu berücksichtigen.

Mit der merge Funktion von meiner vorherigen Antwort (unten), können Sie vermeiden, update aufrufen, die den Anrufer ändert. Es besteht dann keine Notwendigkeit, das Wörterbuch zuerst zu kopieren.

def flatten(data, keys): 
    out = [] 
    values = {} 
    def visit(node, id): 
     if id: 
      id -= 1 
      for key, child in node.items(): 
       values[keys[id]] = key 
       visit(child, id) 
     else: 
      out.append(merge(node, values)) # use merge instead of update 
    visit(data, len(keys)) 
    return out  

Eine Sache, die ich nicht verstehe ist, warum Sie die keys Eingang schützen müssen. Ich sehe nicht, dass sie irgendwo verändert werden.


Zurück Antwort

Wie wäre Liste Verständnis?

def merge(d1, d2): 
    return dict(list(d1.items()) + list(d2.items())) 

[[merge({'foobar': key, 'animal': sub_key}, sub_sub_dict) 
    for sub_key, sub_sub_dict in sub_dict.items()] 
     for key, sub_dict in a.items()] 

Der schwierige Teil der Wörterbücher wurde verschmelzenden ohne update verwendet (was kehrt None).

+0

Ihre Lösung funktioniert mit meiner Probe, aber nicht mit meinen realen Daten, die viel mehr Schichten haben. Ich brauche hier einen rekursiven Algorithmus. – nowox

Verwandte Themen