Ich möchte eine Datei durchlaufen und den Inhalt jeder Zeile in ein tief verschachteltes Diktat schreiben, dessen Struktur durch führende Leerzeichen definiert ist. Dieser Wunsch ist sehr ähnlich wie das dokumentiert here. Ich habe das gelöst, aber jetzt habe ich das Problem, den Fall zu behandeln, in dem wiederholte Schlüssel überschrieben werden, anstatt in eine Liste umgewandelt zu werden.Erstellen eines Baumes/tief geschachtelten Dict mit Listen aus einer eingerückten Textdatei
Im Wesentlichen:
a:
b: c
d: e
a:
b: c2
d: e2
d: wrench
in {"a":{"b":"c2","d":"wrench"}}
werfen, wenn sie in
{"a":[{"b":"c","d":"e"},{"b":"c2","d":["e2","wrench"]}]}
ein in sich geschlossenes Beispiel gegossen werden sollte:
import json
def jsonify_indented_tree(tree):
#convert indentet text into json
parsedJson= {}
parentStack = [parsedJson]
for i, line in enumerate(tree):
data = get_key_value(line)
if data['key'] in parsedJson.keys(): #if parent key is repeated, then cast value as list entry
# stuff that doesn't work
# if isinstance(parsedJson[data['key']],list):
# parsedJson[data['key']].append(parsedJson[data['key']])
# else:
# parsedJson[data['key']]=[parsedJson[data['key']]]
print('Hey - Make a list now!')
if data['value']: #process child by adding it to its current parent
currentParent = parentStack[-1] #.getLastElement()
currentParent[data['key']] = data['value']
if i is not len(tree)-1:
#determine when to switch to next branch
level_dif = data['level']-get_key_value(tree[i+1])['level'] #peek next line level
if (level_dif > 0):
del parentStack[-level_dif:] #reached leaf, process next branch
else:
#group node, push it as the new parent and keep on processing.
currentParent = parentStack[-1] #.getLastElement()
currentParent[data['key']] = {}
newParent = currentParent[data['key']]
parentStack.append(newParent)
return parsedJson
def get_key_value(line):
key = line.split(":")[0].strip()
value = line.split(":")[1].strip()
level = len(line) - len(line.lstrip())
return {'key':key,'value':value,'level':level}
def pp_json(json_thing, sort=True, indents=4):
if type(json_thing) is str:
print(json.dumps(json.loads(json_thing), sort_keys=sort, indent=indents))
else:
print(json.dumps(json_thing, sort_keys=sort, indent=indents))
return None
#nested_string=['a:', '\tb:\t\tc', '\td:\t\te', 'a:', '\tb:\t\tc2', '\td:\t\te2']
#nested_string=['w:','\tgeneral:\t\tcase','a:','\tb:\t\tc','\td:\t\te','a:','\tb:\t\tc2','\td:\t\te2']
nested_string=['a:',
'\tb:\t\tc',
'\td:\t\te',
'a:',
'\tb:\t\tc2',
'\td:\t\te2',
'\td:\t\twrench']
pp_json(jsonify_indented_tree(nested_string))
Wollen Sie sie immer eine Liste sein, oder einfach nur einen dict, wenn es nur ein Element ist? Ich, würde ich immer eine Liste tun und einfach 'defaultdict' verwenden –
die Eingabe sieht mehr wie eine gerichtete Multigraph, nicht Baum, während die Ausgabe ist ein Diktat, nicht Json. Das letzte Element in einem Array wird nicht als Blatt bezeichnet. Sie haben nicht angegeben, was bei mehrstufiger Einrückung passieren soll, nur dass zwei Ebenen ein Diktat einer Liste von Zeichenfolgen bilden sollten. Könnten Sie bitte versuchen, Ihre Absicht (Geschäftslogik) klarer zu machen? – Aprillion
hat das Eingabeformat irgendwo einen Namen? – Aprillion