【问题标题】:Converting an array of string arrays to hierarchical structure将字符串数组的数组转换为层次结构
【发布时间】:2019-06-14 06:47:00
【问题描述】:

想象一下,我排列的数组看起来像这样:

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

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

【问题讨论】:

  • 欢迎来到 SO!你的数据集有多大?天真的方法是针对每个数组,从根开始遍历结构,沿途添加任何丢失的孩子。最后,您将拥有一棵完整的树。但是你会做很多重复的索引。
  • 谢谢!真的。它不是太大——但我想我可以通过利用数组已排序的事实变得更聪明。
  • 您可能可以,但问题是,将这些数组放入某种结构中,例如可以利用这一事实的前缀树,这可能与直接构建树一样慢。跨度>

标签: algorithm go tree hierarchical


【解决方案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]
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-04
    • 2015-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-29
    • 2019-08-07
    相关资源
    最近更新 更多