2017-12-12 4 views
0

Sorry für dumme Frage, aber was mache ich falsch?Löschen von Elementen aus verschachtelten dict rekursiv

Ich habe dict geschachtelt, was ich hoffte, in json zu entleeren.

[{'text': 'Root', 'children': [{'text': 'X', 'children': [None, None], 'id': 2}, {'text': 'Y', 'children': [], 'id': 3}], 'id': 1}] 

Ich muss alle 'None' Werte von ihm entfernen. Hier ist mein Code:

for items in sub_tree_dicts: 
    del_null(items['children']) 

def del_null(childrens): 
    for child in childrens: 
     if child is None: 
      childrens.remove(child) 
     else: 
      del_null(child['children']) 

Leider Code funktioniert nicht wie erwartet, und entfernt nur erste ‚Keine‘ aus der Liste. Wo liege ich falsch?

Danke.

+3

Ändern Sie kein Wörterbuch, während Sie dieses Wörterbuch durchlaufen. Dein 'childrens.remove (child)' bricht deine for-Schleife. – MCBama

+0

Sie wissen, dass Sie die 'None' nicht entfernen müssen, wenn Sie in JSON konvertieren möchten, da' json.dumps() 'sie in' null' ändert ...? – mrCarnivore

+0

@ juanpa.arrivillaga: Sie haben Recht. Ich habe meinen Kommentar korrigiert. – mrCarnivore

Antwort

0

Sie sollten ein Wörterbuch/eine Liste/etc nicht ändern, während Sie über die Liste iterieren. Sie können die Referenz brechen, damit die Schleife nicht weiß, wohin sie gehen soll.

Ich bin ziemlich sicher, es gibt einen besseren Weg, aber die Art, wie ich es Ihren Code zu viel tun würde, ohne Veränderung, ist dies:

for items in sub_tree_dicts: 
    del_null(items['children']) 

def del_null(childrens): 
    invalid_children = [] 
    for child in childrens: 
     if child is None: 
      invalid_children.append(child) 
     else: 
      del_null(child['children']) 
    for child in invalid_children: 
     childrens.remove(child) 
+0

Danke, es funktioniert wie erwartet. Du hast meine Arbeit gerettet. – umaru

0

Sie können dies versuchen:

s = [{'text': 'Root', 'children': [{'text': 'X', 'children': [None, None], 'id': 2}, {'text': 'Y', 'children': [], 'id': 3}], 'id': 1}] 
d = {} 
def filter_none(s, last=None): 
    if last: 
     new_list = [{a:[i for i in b if i is not None] if isinstance(b, list) else b for a, b in c.items()} for c in s] 
     return new_list 
    for a, b in s.items(): 
     if not isinstance(b, list): 
     d[a] = b 
     else: 
     d[a] = filter_none(b, last=a) 

filter_none(s[0]) 
new_d = [d] 

Ausgang:

[{'text': 'Root', 'children': [{'text': 'X', 'children': [], 'id': 2}, {'text': 'Y', 'children': [], 'id': 3}], 'id': 1}] 
+0

Guter Herr Mann. Ich weiß, dass Sie hier wahrscheinlich Effizienz anstreben, aber ich bin ein erfahrener Python-Benutzer und die Lesbarkeit ist hier so grob, dass es sogar eine Weile dauert, bis ich herausfinde, was xD vor sich geht. – MCBama

Verwandte Themen