Golang中结构的递归函数

标签 recursion go

我有以下代码将 *Widget 结构组织成层次结构。 Parent() 返回 ID 为调用者 parentID 的小部件。层次结构最多可达 4 或 5 层。

type Widget struct {
  ID int64
  ParentID int64
}

func (w *Widget) Parent() *Widget {
  // Returns the widget with an ID of w.ParentID
}

我想要实现的是一个函数,它将父级以及父级的父级等聚合到层次结构的顶部,并返回所有父级 ID 的一部分。由于我不知道层次结构的深度,我认为我需要某种编程递归来获取每个父级的父级,这将执行如下操作:

func (w *Widget) AllParents() []*Widget {
  var parentWidgets []*Widget
  x := w.Parent()
  parentWidgets = append(parentWidgets, x)
  y := x.Parent()
  parentWidgets = append(parentWidgets, y)
  ...
  return parentWidgets
}

是否有更惯用的方法来实现这一点?

最佳答案

您只需要在层次结构中越走越高,直到到达根部。假设 Widget.Parent() 返回 nil 如果 Widget 是“根”(意味着它没有父级):

迭代解决方案

下面是一个简单的 for 循环的解决方案:

func (w *Widget) AllParents() []*Widget {
    var ws []*Widget
    for parent := w.Parent(); parent != nil; parent = parent.Parent() {
        ws = append(ws, parent)
    }
    return ws
}

如果在“根”(zero value 用于所有 slice 类型)上调用,此方法将返回 nil。在其他情况下,它将返回“路径”从直接父级通向“根”

这是一个小测试程序。它创建了一个 ID = 0 的根小部件、一个 ID = 1 的子部件和一个 ID = 2 的“孙子”,并打印 AllParents() 分别调用。为了实现 Widget.Parent(),我使用了一个简单的“widget registry”映射。

结果符合预期:

Parents of 0:
Parents of 1: 0
Parents of 2: 1 0

Go Playground 上试试.

var wreg = map[int64]*Widget{}

func (w *Widget) Parent() *Widget {
    // Returns the widget with an ID of w.ParentID
    return wreg[w.ParentID]
}

func main() {
    w := &Widget{0, -1}
    wreg[w.ID] = w
    w2 := &Widget{1, 0}
    wreg[w2.ID] = w2
    w3 := &Widget{2, 1}
    wreg[w3.ID] = w3

    printParents(w)
    printParents(w2)
    printParents(w3)
}

func printParents(w *Widget) {
    fmt.Printf("Parents of %d:", w.ID)
    for _, w := range w.AllParents() {
        fmt.Print(" ", w.ID)
    }
    fmt.Println()
}

递归求解

当然也可以用递归来解决:

func (w *Widget) AllParents() []*Widget {
    if parent := w.Parent(); parent == nil {
        return nil
    } else {
        return append(parent.AllParents(), parent)
    }
}

此解决方案返回“路径”从根目录到直接父目录

用这个实现运行上面的测试程序,输出是:

Parents of 0:
Parents of 1: 0
Parents of 2: 0 1

Go Playground 上试试这个.

关于Golang中结构的递归函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38248857/

相关文章:

JavaScript 如何限制 JSON.stringify 中的递归深度

go - 在 go 应用程序中传递要评估的表达式?

angular - RXJS 扩展从不退出递归调用

java - 我如何可视化查找列表最大数量的递归实现?

Python脚本递归打开目录中的.rar文件

math - golang 中模拟钟形曲线上的值

接口(interface)作为参数。这怎么可能?

php - 在php中递归搜索所有目录中的字符串数组

GO:使用 html/template 提供模板时出错

python - 将 Python Thrift 客户端与 Go gRPC 服务器接口(interface)