2

I have dictionary like this, need to fill it into tree like scheme in array or DB for example:

a = {"seasons": "episodes", "peka": {"lol": "wow", "kek": {"wtf": "is this"}}, "ololo": "wololo"} 

key "seasons" have own ID = 1, Parent_ID = NONE and value "episode" have its own ID = 2 and Parent_ID = 1 , and the same with other item of dictionary.

Guillaume Jacquenot
  • 11,217
  • 6
  • 43
  • 49

2 Answers2

0

You want something like this:

a = {"seasons": "episodes", "peka": {"lol": "wow", "kek": {"wtf": "is this"}}, "ololo": "wololo"}

_id = {}

def newid():
    id = _id.setdefault('foo', 0)
    _id['foo'] += 1
    return id

def flat(dic, parent):
    for k,v in dic.items():
        id = newid()
        yield (id, parent, k, v if not isinstance(v, dict) else None)
        if isinstance(v, dict):
           for tup in flat(v, id):
               yield tup

print list(flat(a, newid()))

Which prints:

[(1, 0, 'seasons', 'episodes'), 
 (2, 0, 'ololo', 'wololo'), 
 (3, 0, 'peka', None), 
 (4, 3, 'kek', None), 
 (5, 4, 'wtf', 'is this'), 
 (6, 3, 'lol', 'wow')]

These are tuples in the form (ID, Parent ID, Key, Value?). I would have prefer to output E(ID, Parent ID, Key) V(ID, Value).

Dan D.
  • 73,243
  • 15
  • 104
  • 123
0

/!\ WARNING the order in a dictionnary is not guaranteed see here

a = { 
      "seasons": "episodes", 
      "peka": {"lol": "wow", "kek": {"wtf": "is this"}}, 
      "ololo": "wololo"
    }

The object a is dictionnary the order of (key, value) is not guaranteed, that is to say random if you do print(a), you have :

{'ololo': 'wololo', 'peka': {'kek': {'wtf': 'is this'}, 'lol': 'wow'}, 'seasons': 'episodes'}

It is another order.

To keep the same order, copy/past this type in the file file.json and user OrderedDict.

file.json:

{ 
  "seasons": "episodes", 
  "peka": {"lol": "wow", "kek": {"wtf": "is this"}}, 
  "ololo": "wololo"
}

Here your solution:

import json
from collections import OrderedDict
from pprint import pprint

with open('file.json', 'r') as filename:
    a = json.load(filename, object_pairs_hook=OrderedDict)


def build_item(_id, parent_id, value):
    return {'ID': _id, 'Parent_ID': parent_id, 'Value': value}


def dfs(_id, root, tree):
    _id += 1
    flat_tree = [build_item(_id, None, root)]
    stack = [(_id, tree)]
    while len(stack) != 0:
        parent_id, tree = stack.pop(0)
        if isinstance(tree, dict):
            for value in tree.keys():
                _id += 1
                flat_tree.append(build_item(_id, parent_id, value))
                stack.append((_id, tree[value]))
        else:
            value = tree
            _id += 1
            flat_tree.append(build_item(_id, parent_id, value))
    return _id, flat_tree


def convert_dict_to_flat_tree(d):
    flat_trees = list()
    _id = 0
    for root, tree in d.items():
        _id, flat_tree = dfs(_id, root, tree)
        flat_trees.extend(flat_tree)
    return flat_trees


flat_tree = convert_dict_to_flat_tree(a)

pprint(flat_tree)

Output:

[{'ID': 1, 'Parent_ID': None, 'Value': 'seasons'},
 {'ID': 2, 'Parent_ID': 1, 'Value': 'episodes'},
 {'ID': 3, 'Parent_ID': None, 'Value': 'peka'},
 {'ID': 4, 'Parent_ID': 3, 'Value': 'lol'},
 {'ID': 5, 'Parent_ID': 3, 'Value': 'kek'},
 {'ID': 6, 'Parent_ID': 4, 'Value': 'wow'},
 {'ID': 7, 'Parent_ID': 5, 'Value': 'wtf'},
 {'ID': 8, 'Parent_ID': 7, 'Value': 'is this'},
 {'ID': 9, 'Parent_ID': None, 'Value': 'ololo'},
 {'ID': 10, 'Parent_ID': 9, 'Value': 'wololo'}]
glegoux
  • 3,505
  • 15
  • 32
  • i am getting this output:{'ID': 1, 'Parent_ID': None, 'Value': 'seasons'} {'ID': 2, 'Parent_ID': 1, 'Value': 'episodes'} {'ID': 3, 'Parent_ID': None, 'Value': 'peka'} {'ID': 4, 'Parent_ID': 3, 'Value': 'lol'} {'ID': 5, 'Parent_ID': 3, 'Value': 'kek'} {'ID': 6, 'Parent_ID': 5, 'Value': 'wtf'} {'ID': 7, 'Parent_ID': 6, 'Value': 'is this'} {'ID': 8, 'Parent_ID': 7, 'Value': 'wow'} {'ID': 9, 'Parent_ID': None, 'Value': 'ololo'} {'ID': 10, 'Parent_ID': 9, 'Value': 'wololo'} – Ron Burgundy Jun 26 '17 at 06:01
  • I change the output to have nice output with `pprint`. Is the result correct ? – glegoux Jun 26 '17 at 06:58
  • In your output value= "wow" have correct id and parent_id (6 ,5) , i have "wow" as id =8 and parent_id = 7 – Ron Burgundy Jun 26 '17 at 07:04
  • It is normal the order in a dictionnary is not guarantee see https://stackoverflow.com/questions/23965870/convert-ordereddict-to-normal-dict-preserving-order – glegoux Jun 26 '17 at 07:12
  • @RonBurgundy it ok for you ? – glegoux Jun 26 '17 at 07:26
  • i have made changes but but still this output [{'ID': 1, 'Parent_ID': None, 'Value': 'seasons'}, {'ID': 2, 'Parent_ID': 1, 'Value': 'episodes'}, {'ID': 3, 'Parent_ID': None, 'Value': 'peka'}, {'ID': 4, 'Parent_ID': 3, 'Value': 'lol'}, {'ID': 5, 'Parent_ID': 3, 'Value': 'kek'}, {'ID': 6, 'Parent_ID': 5, 'Value': 'wtf'}, {'ID': 7, 'Parent_ID': 6, 'Value': 'is this'}, {'ID': 8, 'Parent_ID': 7, 'Value': 'wow'}, {'ID': 9, 'Parent_ID': None, 'Value': 'ololo'}, {'ID': 10, 'Parent_ID': 9, 'Value': 'wololo'}] – Ron Burgundy Jun 26 '17 at 07:27
  • I understand, I fixed that ;). Is it ok now ? – glegoux Jun 26 '17 at 07:43
  • Thank you so much :) really appreciate it , have a nice day :) – Ron Burgundy Jun 26 '17 at 07:47