2016-04-12 9 views
1

Ich würde gerne ein Diktat durchlaufen, dessen Werte eine Mischung aus Listen, Unicode-Strings, Dicts, Bools und Ints sind, um ein eindimensionales Dict zu erzeugen, das alle Schlüssel-Wert-Paare hat . Es ist mir egal, Schlüssel zu erhalten, deren zugehörige Werte dicts sind.Dict mit gemischten Werten in Flat-Dict konvertieren

Ich habe eine rekursive Funktion versucht, aber mir fehlen einige Schritte. Vielleicht muss ich irgendwo .update() oder += verwenden?

def unravel(data): 
    resultsdict = {} 
    for k in data: 
     if isinstance(data[k],dict): 
      unravel(data[k]) 
     else: 
      resultsdict[k] = data[k] 

Beispiel meiner Top-Level-dict Werte:

<type 'list'> 
<type 'bool'> 
<type 'dict'> 
<type 'unicode'> 
<type 'bool'> 
<type 'unicode'> 
<type 'dict'> 
<type 'int'> 
<type 'unicode'> 
+0

Es scheint jedes Mal, wenn Sie tauchen In dieser rekursiven Funktion setzen Sie das Wörterbuch mit resultsdict = {} zurück. Ich denke, das könnte ein Problem sein? – Adib

+0

Also für jedes andere Diktat, das in Ihrem Dict enthalten ist, möchten Sie den Inhalt dieses Dikters bis zur Wurzelebene Ihrer Struktur verschieben? Z.B. '{'a': {'b': 'c'}, 'd': 'e'}' wird zu '{' b ':' c ',' d ':' e '} '? – poke

+0

@Poke Sie sind richtig –

Antwort

4

Sie waren fast da, Sie aber das erstellte Wörterbuch zurückkommen müssen, und aktualisieren Sie das Wörterbuch mit dem zurückgegebenen Wert aus dem rekursiven Aufruf:

def unravel (data): 
    d = {} 
    for k, v in data.items(): 
     if isinstance(v, dict): 
      d.update(unravel(v)) 
     else: 
      d[k] = v 
    return d 

wie folgt verwendet:

>>> unravel({ 'a': { 'b': 'c', 'd': 'e' }, 'f': 'g', 'h': { 'i': 'j' } }) 
{'f': 'g', 'i': 'j', 'b': 'c', 'd': 'e'} 
+0

Ah, danke! –

1

Ihre Methode unravel erstellt eine neue Instanz von resultsdict jedes Mal, wenn es rekursiv aufrufen. Daher gelangen nicht alle Daten sozusagen in das Masterwörterbuch. Versuchen Sie so etwas wie dieses stattdessen:

def unravel(data, resultsdict={}): 
    for k in data: 
     if isinstance(data[k],dict): 
      unravel(data[k], resultsdict) 
     else: 
      resultsdict[k] = data[k] 
    return resultsdict 

In Rekursion Szenarien wie diese, sollten Sie halten die änderbare Datenstruktur mit Ihnen tragen jedes Mal wenn Sie Rekursion.

+1

Bitte vermeide [veränderbare Standardargumente] (http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument), auch wenn du es hier nicht wirklich mutierst. – poke

+0

Eigentlich habe ich diesen Schnitt nicht gesehen. Jetzt ist es einfach kaputt. Versuche 'unravel ({'a': 'b'})' gefolgt von 'unravel ({'b': 'c'})'. Letzterer wird '{' a ':' b ',' b ':' c '} 'jetzt zurückgeben. – poke

+0

Ich mag deine Lösung: D – th3an0maly

0

Sie kann einfach alle Wörterbuch-Tupel entpacken und dann die ganze Sache abflachen

# Turn every key,value pair into a list of tuples 
# [(key, value)] if it's any datatype but dict 
# value.iteritems() otherwise 
grouped_key_value_pairs = [v.iteritems() if isinstance(v,dict) else [(k,v)] for k,v in data.iteritems()] 

# Flatten into a single list of tuples and turn into dict! 
result = dict([kv_pair for group in all_kv_pairs for kv_pair in group]) 
+1

sehr schlau, aber nicht am besten lesbar! –

+0

hinzugefügt einige Kommentare zu versuchen, um zu helfen, aber ich denke, das ist eine ziemlich dichte Liste Verständnis – jfbeltran

+0

ich genieße einen guten One-Liner obwohl .. Ich werde definitiv Ihre Lösung in meiner Bank –

Verwandte Themen