Create jstree hierarchy from parent child pair from table - python

I have a parent child pair from table,
example:
links=(("Tom","Dick"),
("Dick","Harry"),
("Tom","Larry"),
("Bob","Leroy"),
("Bob","Earl"),
("Earl","Joy"),
("Joy","Joy child"),
("Joy","Joy child2"),
("Joy child2", "Maria"))
and I am trying to create jstree from this pairs. I went through various links but cant get this tuple to work. Can anyone please provide a recursive function in python which takes the tuple as mentioned above or any combination of parent-child-grand-child pairs as input and creates a hierarchy by creating a json similar to this format
{
"name": "Tom",
"children": [
{
"name": "Dick"
}
]
}
Thank you in Advance:) I really appreciate your help!

import json
links = (("Tom","Dick"),("Dick","Harry"),("Tom","Larry"),("Tom","Hurbert"),("Tom","Neil"),("Bob","Leroy"),("Bob","Earl"),("Tom","Reginald"))
name_to_node = {}
root = {'name': 'Root', 'children': []}
for parent, child in links:
parent_node = name_to_node.get(parent)
if not parent_node:
name_to_node[parent] = parent_node = {'name': parent}
root['children'].append(parent_node)
name_to_node[child] = child_node = {'name': child}
parent_node.setdefault('children', []).append(child_node)
print json.dumps(root, indent=4)

Related

Possible to set a Python nested dictionary item using single dot-delimited string path?

I'd like to be able to set a nested dictionary item using a single dot-delimited string path. For example, given the following dictionary:
data_dictionary = {
"user_data": {
"first_name": "Some",
"last_name": "Guy",
"phone": "212-111-1234"
}
}
I'd like to be able to set a specific item using a single string, something like this:
data_dictionary['user_data.phone'] = '818-333-4567'
Anyone know of a library or simple technique for accomplishing something like this?
You could define a little helper function:
def set(obj, path, value):
*path, last = path.split(".")
for bit in path:
obj = obj.setdefault(bit, {})
obj[last] = value
set(data_dictionary, "user_data.phone", "123")
data_dictionary
# {'user_data': {'first_name': 'Some', 'last_name': 'Guy', 'phone': '123'}}
You can also subclass dict and override __setitem__:
class my_dict(dict):
def __setitem__(self, item, value):
if "." in item:
head, path = item.split(".", 1)
obj = self.setdefault(head, my_dict())
obj[path] = value
else:
super().__setitem__(item, value)
dd = my_dict({
"user_data": {
"first_name": "Some",
"last_name": "Guy",
"phone": "212-111-1234"
}
})
dd["user_data.phone"] = "123"
dd
# {'user_data': {'first_name': 'Some', 'last_name': 'Guy', 'phone': '123'}}
I suggest something more friendly for nested structures such as Box
Then you can just use dot notation to access as many nests as you want:
from box import Box
data = Box(data_dictionary)
data.user_data.phone = '818-333-4567'
print(data.user_data.phone)
818-333-4567

Python: how to loop through all unknown depth of a tree?

I have a strategic issue of writing a program doing a job.
I have CSV files like:
Column1 Column 2
------- ----------
parent1 [child1, child2, child3]
parent2 [child4, child5, child6]
child1 [child7, child8]
child5 [child10, child33]
... ...
It is unknown how deep each element of those lists will be extended and I want to loop through them.
Code:
def make_parentClass(self):
for i in self.csv_rows_list:
self.parentClassList.append(parentClass(i))
# after first Parent
for i in self.parentClassList:
if i.children !=[]:
for child in i.children:
for z in self.parentClassList:
if str(child) == str(z.node_parent):
i.node_children.append(z)
self.parentClassList.remove(z)
class parentClass():
node_children = []
def __init__(self, the_list):
self.node_parent = the_list[0]
self.children = the_list[1]
The above code might be a solution if I will find a way to iterate. Let me see if you like the question and makes sense now.
Output:
My aim is to build up a treeview through another language but first I need to make this output in JSON format. So the output expected to be something like:
{
paren1:{'child1':{'child7':{}, 'child8':{}},
'child2': {},
'child3': {},
},
parent2: {
'child4':{},
'child5': {
'child10':{},
'child33':{}
},
'child6':{}
}
}
I would recommend a solution using two dictionaries. One nested one with the actually data structure you plan to convert to JSON, and one flat one that will let you actually find the keys. Since everything is a reference in Python, you can make sure that both dictionaries have the exact same values. Carefully modifying the flat dictionary will build your structure for you.
The following code assumes that you have already managed to split each line into a string parent and list children, containing values form the two columns.
json_dict = {}
flat_dict = {}
for parent, children in file_iterator():
if parent in flat_dict:
value = flat_dict[parent]
else:
value = {}
flat_dict[parent] = json_dict[parent] = value
for child in children:
flat_dict[child] = value[child] = {}
Running this produces json_dict like this:
{
'parent1': {
'child1': {
'child7': {},
'child8': {}
},
'child2': {},
'child3': {}
},
'parent2': {
'child4': {},
'child5': {
'child10': {},
'child33': {}
},
'child6': {}
}
}
Here is an IDEOne link to play with.

Recursively build hierarchical JSON tree?

I have a database of parent-child connections. The data look like the following but could be presented in whichever way you want (dictionaries, list of lists, JSON, etc).
links=(("Tom","Dick"),("Dick","Harry"),("Tom","Larry"),("Bob","Leroy"),("Bob","Earl"))
The output that I need is a hierarchical JSON tree, which will be rendered with d3. There are discrete sub-trees in the data, which I will attach to a root node. So I need to recursively go though the links, and build up the tree structure. The furthest I can get is to iterate through all the people and append their children, but I can't figure out to do the higher order links (e.g. how to append a person with children to the child of someone else). This is similar to another question here, but I have no way to know the root nodes in advance, so I can't implement the accepted solution.
I am going for the following tree structure from my example data.
{
"name":"Root",
"children":[
{
"name":"Tom",
"children":[
{
"name":"Dick",
"children":[
{"name":"Harry"}
]
},
{
"name":"Larry"}
]
},
{
"name":"Bob",
"children":[
{
"name":"Leroy"
},
{
"name":"Earl"
}
]
}
]
}
This structure renders like this in my d3 layout.
To identify the root nodes you can unzip links and look for parents who are not children:
parents, children = zip(*links)
root_nodes = {x for x in parents if x not in children}
Then you can apply the recursive method:
import json
links = [("Tom","Dick"),("Dick","Harry"),("Tom","Larry"),("Bob","Leroy"),("Bob","Earl")]
parents, children = zip(*links)
root_nodes = {x for x in parents if x not in children}
for node in root_nodes:
links.append(('Root', node))
def get_nodes(node):
d = {}
d['name'] = node
children = get_children(node)
if children:
d['children'] = [get_nodes(child) for child in children]
return d
def get_children(node):
return [x[1] for x in links if x[0] == node]
tree = get_nodes('Root')
print json.dumps(tree, indent=4)
I used a set to get the root nodes, but if order is important you can use a list and remove the duplicates.
Try follwing code:
import json
links = (("Tom","Dick"),("Dick","Harry"),("Tom","Larry"),("Tom","Hurbert"),("Tom","Neil"),("Bob","Leroy"),("Bob","Earl"),("Tom","Reginald"))
name_to_node = {}
root = {'name': 'Root', 'children': []}
for parent, child in links:
parent_node = name_to_node.get(parent)
if not parent_node:
name_to_node[parent] = parent_node = {'name': parent}
root['children'].append(parent_node)
name_to_node[child] = child_node = {'name': child}
parent_node.setdefault('children', []).append(child_node)
print json.dumps(root, indent=4)
In case you want to format the data as a hierarchy in the HTML/JS itself, take a look at:
Generate (multilevel) flare.json data format from flat json
In case you have tons of data the Web conversion will be faster since it uses the reduce functionality while Python lacks functional programming.
BTW: I am also working on the same topic i.e. generating the collapsible tree structure in d3.js. If you want to work along, my email is: erprateek.vit#gmail.com.

Python: tree like implementation of dict datastructure [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I have dict object something similar to like this,
topo = {
'name' : 'm0',
'children' : [{
'name' : 'm1',
'children' : []
}, {
'name' : 'm2',
'children' : []
}, {
'name' : 'm3',
'children' : []
}]
}
Now, i want to insert one more dict object let's say,
{
'name' : 'ABC',
'children' : []
}
as child of dict named "m2" inside m2's children array.
Could you please suggest how should i go about it?
Should i go for a separate data structure implementation ?
I would suggest you first convert it to a data structure like this:
topo = {
'm0' : {
'm1' : {},
'm2' : {},
'm3' : {},
},
}
That is, you have made every value for the 'name' key be a key in a dictionary, and every value for the 'children' key be the value for that key, and changed it to a dictionary instead of a list.
Now you don't need to assume beforehand the index position where m2 is found. You do need to know that m2 is inside m0, but then you can simply say
topo['m0']['m2']['ABC'] = {}
You can convert between formats with this code:
def verbose_to_compact(verbose):
return { item['name']: verbose_to_compact(item['children']) for item in verbose }
def compact_to_verbose(compact):
return [{'name':key, 'children':compact_to_verbose(value)} for key, value in compact]
Call them like this
compact_topo = verbose_to_compact([topo]) # function expects list; make one-item list
verbose_topo = compact_to_verbose(compact_topo)[0] # function returns list; extract the single item
I am assuming the format you have is the direct interpretation of some file format. You can read it in that way, convert it, work with it in the compact format, and then just convert it back when you need to write it out to a file again.
Your issue is a common Tree structure, you can consider to use http://pythonhosted.org/ete2/tutorial/tutorial_trees.html and populate each node with your dict value (don't reinvent the wheel).
Add it in the dictionary as you normally would, with the use of .append():
topo['children'][1]['children'].append({'name' : 'ABC', 'children' : []})
topo is now:
{
"name": "m0",
"children": [
{
"name": "m1",
"children": []
},
{
"name": "m2",
"children": [
{
"name": "ABC",
"children": []
}
]
},
{
"name": "m3",
"children": []
}
]
}
topo['children'][1]['children'].append({'name': 'ABC', 'children': []})
This adds the new dictionary under the children of the second child of topo:
{'children': [{'children': [], 'name': 'm1'},
{'children': [{'children': [], 'name': 'ABC'}], 'name': 'm2'},
{'children': [], 'name': 'm2'}],
'name': 'm0'}
But I would not use dict and list builtin objects for such a task - I'd rather create my own objects.
topo['children'].append({'name' : 'ABC',
'children' : []
})

Python - how to convert parent child into a nested dictionary

I have a parent child dict that looks like this where the key is child and 0 is root node.
node[0]=[{"parms":{"meta1":"foo"},"name":"RootNoe"}]
node[1]=[{"parent":0,"data":{"parms":{"meta2":"bar"},"name":"country"} }]
node[2]=[{"parent":1,"data":{"parms":{"meta3":"baz"},"name":"day"} }]
I need to create a nested json object that looks like this:
test = {
"params": {"parms":{"meta1":"foo"},
"name": "RootNode",
"children": [
{
"parms":{"meta2":"bar"},
"name":"country",
"children": [
{"parms":{"meta3":"baz"},
"name":"day","children": []}
]
}]
}
How do I do that in python?
You could construct the tree from the definition you have in a loop.
for element in node:
if 'parent' in element:
if 'children' not in node[element['parent']]:
node[element['parent']]['children'] = []
node[element['parent']]['children'].append(element)
del element['parent']
test = node[0]
children needs to be present for this to work, but I'm hoping you get the gist.
Also note that this modifies the node sequence.

Categories

Resources