Algorithm 将字符串数组数组转换为层次结构

Algorithm 将字符串数组数组转换为层次结构,algorithm,go,tree,hierarchical,Algorithm,Go,Tree,Hierarchical,假设我对数组进行了排序,如下所示: ["A", "B", "C"] ["A", "B", "D"] ["A", "E"] ["F", "G"] 我现在想把它转换成 type Node struct { NodeID string Children []Node } 我试图写一种通过递归实现的方法 这是我目前用Go编写的尝试: func Test_toNodes(t *testing.T) { in := [][]string{ {"A", "B",

假设我对数组进行了排序,如下所示:

["A", "B", "C"]
["A", "B", "D"]
["A", "E"]
["F", "G"]
我现在想把它转换成

type Node struct {
     NodeID string
     Children []Node
}
我试图写一种通过递归实现的方法

这是我目前用Go编写的尝试:

func Test_toNodes(t *testing.T) {
    in := [][]string{
        {"A", "B", "C"},
        {"A", "B", "D"},
        {"A", "E"},
        {"F", "G"},
    }

    want := []Node{
        {
            Name: "A",
            Children: []Node{
                {
                    Name: "B",
                    Children: []Node{
                        {
                            Name: "C",
                        },
                        {
                            Name: "D",
                        },
                    },
                },
                {
                    Name: "E",
                },
            },
        },
        {
            Name: "F",
        },
    }

    got := toNodes(in)
    if !reflect.DeepEqual(got, want) {
        t.Fatalf("got %v, want %v", got, want)
    }
}

func toNodes(in [][]string) []Node {
    var (
        tmp [][]string
        out []Node
    )

    for i, hierarchy := range in {
        current := nodeAt(in, i)
        next := nodeAt(in, i+1)

        if current == next {
            if len(hierarchy) > 0 {
                tmp = append(tmp, hierarchy[1:])
            }
        } else {
            out = append(out, Node{
                Name:     current,
                Children: toNodes(tmp),
            })
        }
    }

    return out
}

func nodeAt(h [][]string, i int) string {
    if i > len(h)-1 {
        return ""
    }
    v := h[i]
    if len(v) == 0 {
        return ""
    }
    return v[0]
}

这显然不能呈现正确的结果,也不能处理所有的边缘情况——因此这里有一个通用的“算法”可以应用吗?

这里是一个递归解决方案,它传递给您的示例输入。关于输入和可能存在的边缘情况,您没有说太多,所以如果在某些输入上失败,请告诉我,并提供输入

我还修正了你在测试中的预期结果。您忘记了
F
节点
G
的子节点。希望这有帮助

type Node struct {
    Name     string
    Children []Node
}

func Test_toNodes(t *testing.T) {
    in := [][]string{
        {"A", "B", "C"},
        {"A", "B", "D"},
        {"A", "E"},
        {"F", "G"},
    }

    want := []Node{
        {
            Name: "A",
            Children: []Node{
                {
                    Name: "B",
                    Children: []Node{
                        {
                            Name: "C",
                        },
                        {
                            Name: "D",
                        },
                    },
                },
                {
                    Name: "E",
                },
            },
        },
        {
            Name: "F",
            Children: []Node{
                {
                    Name: "G",
                },
            },
        },
    }

    got := toNodes(in, 0, 0, len(in))
    if !reflect.DeepEqual(got, want) {
        t.Fatalf("got %v, want %v", got, want)
    }
}

func toNodes(in [][]string, i, j, k int) []Node {
    res := []Node{}

    for m := j; m < k; m++ {
        curr := nodeAt(in, i, m)
        next := nodeAt(in, i, m+1)
        if next != curr {
            children := toNodes(in, i+1, j, m+1)
            if len(children) == 0 {
                children = nil
            }
            res = append(res, Node{
                Name:     curr,
                Children: children,
            })
            j = m + 1
        }
    }

    return res
}

func nodeAt(h [][]string, i, j int) string {
    if j >= len(h) || i >= len(h[j]) {
        return ""
    }
    return h[j][i]
}
类型节点结构{
名称字符串
子节点[]节点
}
函数测试节点(t*testing.t){
输入:=[]字符串{
{“A”、“B”、“C”},
{“A”、“B”、“D”},
{“A”,“E”},
{“F”,“G”},
}
需要:=[]节点{
{
名称:“A”,
子节点:[]节点{
{
名称:“B”,
子节点:[]节点{
{
名称:“C”,
},
{
名称:“D”,
},
},
},
{
名称:“E”,
},
},
},
{
名称:“F”,
子节点:[]节点{
{
名称:“G”,
},
},
},
}
got:=音调(in,0,0,len(in))
if!reflect.DeepEqual(得到,想要){
t、 Fatalf(“得到%v,想要%v”,得到,想要)
}
}
函数节点(在[]字符串中,i,j,k int)[]节点{
res:=[]节点{}
对于m:=j;m=len(h)| i>=len(h[j]){
返回“”
}
返回h[j][i]
}

欢迎来到SO!您的数据集有多大?最简单的方法是对每个数组,从根开始遍历结构,并在过程中添加任何缺少的子元素。最后,你会有一棵完整的树。但是你会做很多重复的索引。谢谢!对。它不是太大,但我想我可以更聪明地利用数组是排序的这一事实。你可能可以,但问题是,将这些数组放入某种结构中,如前缀树,可以利用这一事实,这可能与直接构建树一样缓慢。