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

问题描述 投票:1回答:1

想象一下,我已经对数组进行了排序:

["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]
}

这显然无法呈现正确的结果,并且不能处理所有边缘情况 - 所以是否有一般的“算法”,可以在这里应用?

algorithm go tree hierarchical
1个回答
1
投票

这是一个传递样本输入的递归解决方案。你没有多说输入和可能有的边缘情况,所以让我知道它是否在某些输入上失败并提供输入。

我还在测试中修正了你的预期结果。你忘记了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]
}
© www.soinside.com 2019 - 2024. All rights reserved.