如何为有序数字构建树?

how to build a tree for ordered numbers?

我正在尝试根据输入的数字构建一棵树(字典)。我对树的主要标准是一个级别中的所有节点都在同一范围内。 (来自parent的一系列数据)我想你会从我的例子中得到灵感-

请看例子

    input_list=[1,2,3,4,5,
        5.1,5.2,5.3,5.4,
        6,7,8,8.1,8.2,8.21,
        8.22,8.22,8.23,8.24,8.25,
        8.3,8.4,8.5,
        9,9.1,9.2,9.3,10,11,12]

    expected_out_put={
        0: [1,2,3,4,5,6,7,8,9,10,11,12],
        5: [5.1,5.2,5.3,5.4],
        8: [8.1,8.2,8.3,8.4,8.5],
        8.2: [8.21,8.22,8.23,8.24,8.25],
        9: [9.1,9.2,9.3],
    }
    

我最初尝试建造一棵树。这仅适用于数据 1-9,任何人都可以帮助我找到更好的解决方案 这就是我尝试的方式

    class Section:
        FIRST_TIME=False
        def intialise(self):
            self.rank=0
            self.child_sections.clear()
            self.next_value_diff=10000
            parent=None
        def __init__(self,**Kwargs): 
            self.rank = Kwargs['rank']
            self.child_sections=[]
            self.next_value_diff=0
        def set_next_value_diff(self,value):
            self.next_value_diff=value
            
        def is_sibling(self,section_obj):
            c_diff=abs(section_obj.rank-self.rank)
            print('c_difference is '+str(c_diff)+"and prev differnec is"+str(self.next_value_diff))
            if(self.next_value_diff>c_diff):
                return False
            return True
            
        def add_child(self,section_obj):
            prev_root=self
            print("Self rank is"+str(self.rank))
            print(len(self.child_sections))
            print([i.rank for i in self.child_sections])
    
            if(len(self.child_sections)>0):
                prev_root=self.child_sections[-1]
                
            c_diff=abs(section_obj.rank-prev_root.rank)    
            print("addred rank "+str(section_obj.rank)+" prev "+str(prev_root.rank)+"diffrenc "+str(c_diff))
      
            
            section_obj.next_value_diff=c_diff
            self.child_sections.append(section_obj)
            print("added "+str(section_obj.rank)+"under "+str(self.rank)+"diffrenc "+str(c_diff))
            return 
        
    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]
    data_stack=[i*1000 for i in data_stack]
    data_stack.reverse()
    print(data_stack)
    def create_root(parent):
        print('Current parent is'+str(parent.rank))
        global data_stack
        while( (len(data_stack)>0) and (not parent.is_sibling(Section(rank=data_stack[-1])))):
            rank_value=data_stack.pop()
            print("poped value of "+str(rank_value))
            section_obj=Section(rank=rank_value)      
            if(len(parent.child_sections)>0):
                print("Found its  "+str(parent.rank)+"has "+str(len(parent.child_sections))+" childrens")
                #check any child exists
                #sub_section is a sibling
                child=parent.child_sections[-1]
                print("checking simplinag "+str(section_obj.rank)+" : aginst child "+str(child.rank))
              
                if child.is_sibling(section_obj):
                    print("yes he is simpler with "+str(rank_value)+" : aginst child "+str(child.rank))
                    parent.add_child(section_obj)               
                else:
                    print('not sibler')
                    nextparent=parent.child_sections.pop()
                    print('popped '+str(nextparent.rank))
                    print("Koids")
                    print([i.rank for i in nextparent.child_sections])
                    nextparent.add_child(section_obj)
    
                    print('recurent call happenmd')
                    parent.add_child(create_root(nextparent))
                    
            else:
                print("No child at the time of"+str(rank_value))
                parent.add_child(section_obj)
                print("added to parent at the time of"+str(rank_value))
        return parent
        
        
    parent=Section(rank=0)
    parent.intialise()
    parent=create_root(parent)
    print(parent.rank)
    print([j.rank for j in parent.child_sections])
    for k in parent.child_sections:
        print('kids of'+str(k.rank))
        print([m.rank for m in k.child_sections])
        for m in k.child_sections:
            print('kids of'+str(m.rank))
            print([n.rank for n in m.child_sections])
            for n in m.child_sections:
                print('kids of'+str(n.rank))
                print([s.rank for s in n.child_sections])

首先你得到键,它们是零加上列表元素的唯一整数部分:

keys=set(map(lambda x: 0 if isinstance(x, int) else int(x), input_list))

那应该给你

{0, 5, 8, 9}

那么,你可以通过多种方式生成int、list的字典,例如:

{k: [y for y in input_list if (k==0 and isinstance(y, int)) or (k>0 and not isinstance(y, int) and int(y)==k)] for k in keys}

这是一个用你的键生成的字典,在里面,所有的列表只选择那些符合要求的元素(整数或key.decimal)

尝试一下:

Imports:我正在使用来自标准库的 defaultdictgroupby

from collections import defaultdict
from itertools import groupby

两个 辅助函数 供以后使用:

def tuple_to_key(tup):
    if len(tup) == 2:
        return int(tup[0])
    return float(f"{tup[0]}.{''.join(n for n in tup[1:-1])}")

def childs_to_float(childs):
    return [float(f"{tup[0]}.{''.join(n for n in tup[1:])}") for tup in childs]

步骤 1:建立级别(假设 input_list 已排序):

levels = defaultdict(list)
for tup in [(lst[0],) if len(lst) == 1 else (lst[0],) + tuple(lst[1])
            for lst in [str(n).split('.') for n in input_list]]:
    levels[len(tup)].append(tup)

结果如下:

{
 1: [('1',), ('2',), ('3',), ('4',), ('5',), ('6',), ('7',), ('8',), ('9',), ('10',), ('11',), ('12',)],
 2: [('5', '1'), ('5', '2'), ('5', '3'), ('5', '4'),
     ('8', '1'), ('8', '2'), ('8', '3'), ('8', '4'), ('8', '5'),
     ('9', '1'), ('9', '2'), ('9', '3')],
 3: [('8', '2', '1'), ('8', '2', '2'), ('8', '2', '2'), ('8', '2', '3'), ('8', '2', '4'), ('8', '2', '5')]
}

步骤 2:查找父子关系:

output = {
    parent: childs_to_float(childs)
    for level in levels.keys() if level > 1
    for parent, childs in groupby(levels[level], key=tuple_to_key)
}
if 1 in levels:
    childs = [int(t[0]) for t in levels[1]]
    output[min(childs) - 1] = childs

输出:

{
 0: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
 5: [5.1, 5.2, 5.3, 5.4],
 8: [8.1, 8.2, 8.3, 8.4, 8.5],
 8.2: [8.21, 8.22, 8.22, 8.23, 8.24, 8.25],
 9: [9.1, 9.2, 9.3]
}

我确定里面有很多皱纹...