I am trying build a tree (dictionary ) from input numbers. My main criteria for the tree is all the nodes in a level are in a same range. ( a series of data from parent) I think you will get idea from my examples-
Please see the example
JavaScript
x
16
16
1
input_list=[1,2,3,4,5,
2
5.1,5.2,5.3,5.4,
3
6,7,8,8.1,8.2,8.21,
4
8.22,8.22,8.23,8.24,8.25,
5
8.3,8.4,8.5,
6
9,9.1,9.2,9.3,10,11,12]
7
8
expected_out_put={
9
0: [1,2,3,4,5,6,7,8,9,10,11,12],
10
5: [5.1,5.2,5.3,5.4],
11
8: [8.1,8.2,8.3,8.4,8.5],
12
8.2: [8.21,8.22,8.23,8.24,8.25],
13
9: [9.1,9.2,9.3],
14
}
15
16
I tried to build a tree initially. This will work only for the data 1-9, anybody help me to find a better solution This is how I tried
JavaScript
1
93
93
1
class Section:
2
FIRST_TIME=False
3
def intialise(self):
4
self.rank=0
5
self.child_sections.clear()
6
self.next_value_diff=10000
7
parent=None
8
def __init__(self,**Kwargs):
9
self.rank = Kwargs['rank']
10
self.child_sections=[]
11
self.next_value_diff=0
12
def set_next_value_diff(self,value):
13
self.next_value_diff=value
14
15
def is_sibling(self,section_obj):
16
c_diff=abs(section_obj.rank-self.rank)
17
print('c_difference is '+str(c_diff)+"and prev differnec is"+str(self.next_value_diff))
18
if(self.next_value_diff>c_diff):
19
return False
20
return True
21
22
def add_child(self,section_obj):
23
prev_root=self
24
print("Self rank is"+str(self.rank))
25
print(len(self.child_sections))
26
print([i.rank for i in self.child_sections])
27
28
if(len(self.child_sections)>0):
29
prev_root=self.child_sections[-1]
30
31
c_diff=abs(section_obj.rank-prev_root.rank)
32
print("addred rank "+str(section_obj.rank)+" prev "+str(prev_root.rank)+"diffrenc "+str(c_diff))
33
34
35
section_obj.next_value_diff=c_diff
36
self.child_sections.append(section_obj)
37
print("added "+str(section_obj.rank)+"under "+str(self.rank)+"diffrenc "+str(c_diff))
38
return
39
40
data_stack=[1.0, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 2.1, 2.11, 2.12, 2.13, 2.14, 2.15, 2.16, 2.17, 2.18, 2.19, 2.2, 2.21, 2.22, 2.23, 2.24, 2.25, 2.26, 2.27, 2.28, 2.34, 2.35, 2.36, 2.37, 2.38, 2.39, 2.4, 2.42, 2.43, 2.44, 2.45, 2.46]
41
data_stack=[i*1000 for i in data_stack]
42
data_stack.reverse()
43
print(data_stack)
44
def create_root(parent):
45
print('Current parent is'+str(parent.rank))
46
global data_stack
47
while( (len(data_stack)>0) and (not parent.is_sibling(Section(rank=data_stack[-1])))):
48
rank_value=data_stack.pop()
49
print("poped value of "+str(rank_value))
50
section_obj=Section(rank=rank_value)
51
if(len(parent.child_sections)>0):
52
print("Found its "+str(parent.rank)+"has "+str(len(parent.child_sections))+" childrens")
53
#check any child exists
54
#sub_section is a sibling
55
child=parent.child_sections[-1]
56
print("checking simplinag "+str(section_obj.rank)+" : aginst child "+str(child.rank))
57
58
if child.is_sibling(section_obj):
59
print("yes he is simpler with "+str(rank_value)+" : aginst child "+str(child.rank))
60
parent.add_child(section_obj)
61
else:
62
print('not sibler')
63
nextparent=parent.child_sections.pop()
64
print('popped '+str(nextparent.rank))
65
print("Koids")
66
print([i.rank for i in nextparent.child_sections])
67
nextparent.add_child(section_obj)
68
69
print('recurent call happenmd')
70
parent.add_child(create_root(nextparent))
71
72
else:
73
print("No child at the time of"+str(rank_value))
74
parent.add_child(section_obj)
75
print("added to parent at the time of"+str(rank_value))
76
return parent
77
78
79
parent=Section(rank=0)
80
parent.intialise()
81
parent=create_root(parent)
82
print(parent.rank)
83
print([j.rank for j in parent.child_sections])
84
for k in parent.child_sections:
85
print('kids of'+str(k.rank))
86
print([m.rank for m in k.child_sections])
87
for m in k.child_sections:
88
print('kids of'+str(m.rank))
89
print([n.rank for n in m.child_sections])
90
for n in m.child_sections:
91
print('kids of'+str(n.rank))
92
print([s.rank for s in n.child_sections])
93
Advertisement
Answer
Here’s an attempt:
Imports: I’m working with defaultdict
and groupby
, both from the standard library:
JavaScript
1
3
1
from collections import defaultdict
2
from itertools import groupby
3
Two helper functions for later:
JavaScript
1
8
1
def tuple_to_key(tup):
2
if len(tup) == 2:
3
return int(tup[0])
4
return float(f"{tup[0]}.{''.join(n for n in tup[1:-1])}")
5
6
def childs_to_float(childs):
7
return [float(f"{tup[0]}.{''.join(n for n in tup[1:])}") for tup in childs]
8
Step 1: Establishing the levels (the assumption is that input_list
is sorted):
JavaScript
1
5
1
levels = defaultdict(list)
2
for tup in [(lst[0],) if len(lst) == 1 else (lst[0],) + tuple(lst[1])
3
for lst in [str(n).split('.') for n in input_list]]:
4
levels[len(tup)].append(tup)
5
The result looks like:
JavaScript
1
8
1
{
2
1: [('1',), ('2',), ('3',), ('4',), ('5',), ('6',), ('7',), ('8',), ('9',), ('10',), ('11',), ('12',)],
3
2: [('5', '1'), ('5', '2'), ('5', '3'), ('5', '4'),
4
('8', '1'), ('8', '2'), ('8', '3'), ('8', '4'), ('8', '5'),
5
('9', '1'), ('9', '2'), ('9', '3')],
6
3: [('8', '2', '1'), ('8', '2', '2'), ('8', '2', '2'), ('8', '2', '3'), ('8', '2', '4'), ('8', '2', '5')]
7
}
8
Step 2: Finding the parent child relationships:
JavaScript
1
9
1
output = {
2
parent: childs_to_float(childs)
3
for level in levels.keys() if level > 1
4
for parent, childs in groupby(levels[level], key=tuple_to_key)
5
}
6
if 1 in levels:
7
childs = [int(t[0]) for t in levels[1]]
8
output[min(childs) - 1] = childs
9
Output:
JavaScript
1
8
1
{
2
0: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
3
5: [5.1, 5.2, 5.3, 5.4],
4
8: [8.1, 8.2, 8.3, 8.4, 8.5],
5
8.2: [8.21, 8.22, 8.22, 8.23, 8.24, 8.25],
6
9: [9.1, 9.2, 9.3]
7
}
8
I’m sure there are plenty of wrinkles in it …