Convert map to tree in Go

huangapple go评论100阅读模式
英文:

Convert map to tree in Go

问题

我有一个非常具体的问题,我无法找到解决方案。

我有一个map[string]Metric,我想将其转换为树形结构,以便在前端中使用。Metric接口具有Path()Name()方法,Name()方法返回以句点分隔的路径的最后一部分(因此路径为'my.awesome.metric'意味着该指标的名称为'metric')。
树应该按路径排序,并且应该包含IndexNode。该结构的定义如下:

type IndexNode struct {
    Name string
    Path string
    Children []*IndexNode
}

因此,像这样的映射:

{
    my.awesome.metric.downloads
    my.awesome.othermetric.downloads
    my.awesome.othermetric.uploads
    my.other.cool.metric
}

应该生成如下的树形结构:(对于粗糙的ASCII艺术表示我表示抱歉)

     +-- other -- cool -- metric
     |
my --+             +-- metric -- downloads
     |             |
     +-- awesome --+                 +-- downloads
                   |                 |
                   +-- othermetric --+
                                     |
                                     +-- uploads

请注意,我只有一个根节点(在本例中为'my')。树中的顺序对我来说并不重要。

我已经尽力了,但无法解决它... 在大量搜索之后(只显示了如何创建二叉搜索树和GoDS库),我决定在这里提出我的第一个问题 😊

谢谢你的帮助!

英文:

I have a very specific problem, I cannot figure out a solution for.

I have a map[string]Metric, which I want to convert into a tree for using in a frontend. The Metric interface looks has a Path() and a Name() Method, the name method returns the last part of a period-separated path (so a path of 'my.awesome.metric' will mean that this metric has the name 'metric')
The tree should be sorted by the path and should contain IndexNodes. This struct looks like this:

type IndexNode struct {
    Name string
    Path string
    Children []*IndexNode
}

So a map like this:

{
    my.awesome.metric.downloads
    my.awesome.othermetric.downloads
    my.awesome.othermetric.uploads
    my.other.cool.metric
}

Should lead to a tree like this: (sorry for the crude ascii art)

     +-- other -- cool -- metric
     |
my --+             +-- metric -- downloads
     |             |
     +-- awesome --+                 +-- downloads
                   |                 |
                   +-- othermetric --+
                                     |
                                     +-- uploads

Note that I only ever have one root node (my in this case). The order inside of the tree does not matter to me.

I tried my best and cannot figure it out... After lots of googleing (which only showed me how to create binary search trees and the GoDS library), I resigned and decided to ask my very first question here 😊

Thanks for your help!

答案1

得分: 1

Children更改为map[string]*IndexNode,你就完成了一半的工作。如果你不介意查找速度变慢,你可以使用切片,但这意味着你需要每次遍历树时在切片中搜索所需的子节点。在这种情况下,使用map更快更容易。

现在,你只需要编写一个递归函数,沿着树向下移动,根据路径中的每个元素创建所需的节点,直到到达末尾。

不幸的是,我无法立即访问示例,因为我的所有代码都在另一台电脑上 Convert map to tree in Go

以下是一个简单的示例:

type Tree struct {
    Parent   *Tree
    Children map[string]*Tree
    Payload  bool // 在这里放入你的数据
}

func NewTree(parent *Tree, path []string, payload bool) *Tree {
    if parent == nil {
        parent = &Tree{nil, map[string]*Tree{}, false}
    }
    if len(path) == 0 {
        parent.Payload = payload
        return parent
    }

    child := parent.Children[path[0]]
    if child == nil {
        child = &Tree{parent, map[string]*Tree{}, false}
        parent.Children[path[0]] = child
    }
    return NewTree(child, path[1:], payload)
}

用法:

root := NewTree(nil, nil, false)
newnode := NewTree(root, []string{"A", "B", "C"}, true)

在 Go Playground 上试一试!

英文:

Change Children to map[string]*IndexNode and you are halfway there. If you don't mind it being a lot slower to look stuff up, you can use a slice, but this means you need to search the slice to find the child you want every time you traverse the tree. A map is faster and easier in this case.

Now you just need to write a recursive function that steps down the tree, making nodes as needed for each element in the path until it reaches the end.

Unfortunately I don't have ready access to an example, all my code in on my other computer Convert map to tree in Go

A quick and dirty example:

type Tree struct {
    Parent *Tree
    Children map[string]*Tree
    Payload bool // Your data here
}

func NewTree(parent *Tree, path []string, payload bool) *Tree {
    if parent == nil {
        parent = &Tree{nil, map[string]*Tree{}, false}
    }
    if len(path) == 0 {
        parent.Payload = payload
        return parent
    }
    
    child := parent.Children[path[0]]
    if child == nil {
        child = &Tree{parent, map[string]*Tree{}, false}
        parent.Children[path[0]] = child
    }
    return NewTree(child, path[1:], payload)
}

Usage:

root := NewTree(nil, nil, false)
newnode := NewTree(root, []string{"A", "B", "C"}, true)

Try it on the Go Playground!

答案2

得分: 0

这是使用映射的解决方案,遍历它可以帮助你填充数据结构。可以在树形导航中的"Parent xxx Child xxx"处创建节点。链接:https://play.golang.org/p/sVqBCVgiBG

英文:

Here's a solution using a map, traversing it can help you populate the data structure. Can create the nodes where it says "Parent xxx Child xxx" in the tree navigation https://play.golang.org/p/sVqBCVgiBG

huangapple
  • 本文由 发表于 2017年7月26日 07:01:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/45314812.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定