Python 3.6 Dynamic Dictionary Dynamic Update

I have a file like:

HP;1<br/>
MN;stringval<br/>
IS/VD1;32.00<br/>
IS/HD1;1.34<br/>
IS/E/ID;362.0000000<br/>
IS/OLVD;0.0000000<br/>
ISN/I/HFD;3283.8999023<br/>
D1/I/MF;7.3059464<br/>
D1/I/P;32.0388412<br/>
D1/E/E;2778.4829102<br/>
D1/S1/SB/I/P;32.0388412<br/>
EN;5145<br/>

After the ";" there is a value that I want to put in the dictionary.

Every word that follows /is a key.

My ultimate goal is to have the following dictionary:

{"HP":1.0,"MN":'stringval',"IS":{"VD1":32.00,"HD1":1.34,"E":{"ID":362.0000000},"OLVD":0.0000000},"ISN":{"I":{"HFD":3283.8999023}},"D1":{"I":{"MF":7.3059464,"P":32.03884},"E":{"E":2778.4829102},"S1":{"SB":{"I":{"P":32.0388412}}}},"EN":5145}

I do not know the maximum number of levels of the final dictionary.

I tried the following code:

fid = open(myfile,mode='r')
content=fid.readlines()
content = [x.replace(' ','').strip() for x in content]
outdata = dict()
for i in content:

    dict_struct = i.split(';')[0]
    val = i.split(';')[-1]
    n_lev = dict_struct.count('/')
    test2 = '{"' + dict_struct.replace('/', '":{"') + '":' + val + '}' * (n_lev + 1)

    try:
        outdata.update(eval(test2))
        print(test2)
    except:
        test2 = '{"' + dict_struct.replace('/', '":{"') + '":"' + val + '"' + '}' * (n_lev + 1)
        print(test2)
        outdata.update(eval(test2))

This code does not work because it update()actually overwrites some of the inputs; this is the conclusion:

{"HP": 1, "MN": "stringval", "IS": {"OLVD": 0.0}, "ISN": {"I": {"HFD": 3283.8999023}}, "D1": {"S1": {"SB": {"I": {"P": 32.0388412}}}}, "EN": 5145}

Could you give me some advice?

+4
source share
2 answers

You can build a tree using the staructure dictionary

here is my solution

import json,sys


def update(k,v):
    d = {}
    d[k]=v
    return d 



def processRow(row):
    value = row.split(';', 2)
    #print(value)
    if len(value)<=1:
        return 
    keys = value[0].split('/')
    v=value[1]

    try:
        v=[float(v)]
    except:
        v=[v]

    for i, e in reversed(list(enumerate(keys))):
        v = update(e,v)

    return v

def updateTree(dic, tree):
    #print("IN %s -> OUT %s" % (dic, json.dumps(tree, indent = 4)))
    #print()
    for key in dic:
        value=dic[key]
        subtree = tree.get(key)

        if subtree and isinstance(subtree, dict):
            updateTree(value,subtree)
        elif subtree and isinstance(subtree, list) and isinstance(value, list):
            subtree.extend(value)
        elif not(subtree):
            tree.update(dic)
        else:
            sys.stderr.write ("ERROR: incoherent data type %s vs %s" % (dic, json.dumps(tree, indent = 4)))


txt = "HP;1\nMN;stringval\nIS/VD1;32.00\nIS/HD1;1.34\nIS/E/ID;362.0000000\n"
rows = txt.split('\n')
x = []

t={}
for row in rows:
    v = processRow(row)
    if (v):
        updateTree(v,t)

print (json.dumps(t, indent = 4))

result

{
    "HP": [
        1.0
    ],
    "MN": [
        "stringval"
    ],
    "IS": {
        "VD1": [
            32.0
        ],
        "HD1": [
            1.34
        ],
        "E": {
            "ID": [
                362.0
            ]
        }
    } }
+2
source

To create a nested dictionary, you need to do basic string parsing:

>>> S = "D1/S1/SB/I/P;32.0388412"
>>> D = {}
>>> parts1 = S.split(';', 2)
>>> parts2 = parts1[0].split('/')
>>> D2 = D
>>> for i, e in enumerate(parts2):
...     if i == len(parts2) - 1:
...         D2[e] = parts1[1]
...     else:
...         D3 = {}
...         D2[e] = D3
...         D2 = D3
... 
>>> D
{'D1': {'S1': {'SB': {'I': {'P': '32.0388412'}}}}}
+1
source

Source: https://habr.com/ru/post/1695824/


All Articles