想象一下,我已经对数组进行了排序:
["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]
}