2016-05-03 7 views
4

Ich analysiere einige XML-Daten von Open Street Map in JSON (später in eine Datenbank hochgeladen werden). Es ist groß, also verwende ich Iserparse. Ich habe einige Tags, dieWie Rekursion zu verwenden, um Wörterbücher zu verschachteln, während mit vorhandenen Datensätzen integriert wird

<tag 'k'=stringA:stringB:stringC 'v'=value> 

wie diese aussehen, die ich in

{stringA: {stringB: {stringC: value} } } 

ich so mit einem hässlichen hard getan haben, analysieren möchten. Ich möchte jedoch eine Funktion erstellen, die Rekursion verwendet, um dasselbe Problem zu beheben, falls der Attributwert 'k' beliebig viele ':' enthält.

Ich habe dieses

def nestify(l): 
    """Takes a list l and returns nested dictionaries where each element from 
    the list is both a key to the inner dictionary and a value to the outer, 
    except for the last element of the list, one which is only a value. 
    For best understanding, feed w = [ 'a', 'b', 'c', 'd', 'e', 'f', 'v'] to the 
    function and look at the output.""" 
    n = len(l) 
    if n==2: 
     key = l[0] 
     value = l[1] 
    else: 
     key = l[0] 
     value = nestify(l[1:]) 

    return {key:value}     

die funktioniert. (Sie müssen die Schlüssel und den Wert zuerst in eine Liste eintragen.) Außer wirklich nicht, weil es immer ein neues Wörterbuch bildet. Ich brauche es, um die vorherigen Daten zu respektieren und zu integrieren. Zum Beispiel, wenn mein Parser trifft

<tag 'k'=a:b:c 'v'=1 /> 

und dann in dem gleichen Element

<tag 'k'=a:d:e 'v'=2 /> 

ich es brauche

{a: {'b': {'c' : 1}, 'd' : {'e' : 2}}} 

und nicht

{a: {'b' : {'c' : 1}}} 

{a: {'d' : {'e' : 2}}} 

Ich habe zu machen versuchte diesen Code:

def smart_nestify(l, record): 
n = len(l) 
if n==2: 
    key = l[0] 
    value = l[1] 
else: 
    key = l[0] 
    value = smart_nestify(l[1:], key) 
if key not in record: 
    return {key:value}     
else: 
    record[key] = value 
    return record 

aber es schreibt immer noch und gibt nur den neuesten Datensatz zurück. Warum das? Wie kann ich diesen Code reparieren?

Antwort

0

Hier ist ein „intelligenter“ nestify ist, die eine Liste l in das Wörterbuch verschmilzt record:

def smarter_nestify(l, record): 
    if len(l) == 2: 
     return {l[0]: l[1]} 
    key = l.pop(0) 
    record[key] = smarter_nestify(l, record.get(key, {})) 
    return record 

Bei jeder Rekursion wird das erste Element aus der Liste ausgegeben und der Wert von der nächsten Ebene des Dictio zusammengeführt Nary record.get(key, {}).

Sie können es mit zwei Listen wie folgt aufrufen:

l = ['a', 'b', 'c', 1] 
record = smarter_nestify(l, {}) 

l = ['a', 'd', 'e', 2] 
record = smarter_nestify(l, record) 
print record 
-1

Manchmal ist es besser, nur Iteration statt Rekursion zu verwenden. Hier ist die iterative Antwort.

g_values = dict() 
def make_nested(l): 
    """ 
    l is the array like you have for nestify 
    e.g., ['a', 'b', 'c', 1 ] or ['a', 'd', 'e', 2] 
    """ 
    global g_values 
    value = l[-1] ; l = l[:-1] 
    last_dict = None 
    for x in l[:-1]: 
     mp_temp = last_dict if last_dict is not None or g_values 
     last_dict = mp_temp.get(x) 
     if last_dict is None: 
      mp_temp[x] = dict() 
      last_dict = mp_temp[x] 
    last_dict[l[-1]] = value 

Während ich es nicht testen haben, können Sie auch so etwas wie dieses rekursiv versuchen:

def make_nested(values, l): 
    if len(l == 2): 
     values[l[0]] = l[1] 
     return 
    mp = values.get(l[0]) 
    if mp is None: 
     values[l[0]] = dict() 
     make_nested(values[l[0]], l[1:]) 
    else: 
     make_nested(mp, l[1:])  
+0

Ich hatte eine iterative Lösung, ich war für die rekursive suchen. – ASignor