【问题标题】:Having some issues recursively printing a complete list of a tree-like structure递归打印树状结构的完整列表时遇到一些问题
【发布时间】:2020-03-22 18:39:30
【问题描述】:

我在为具有 n 个命令的 CLI 工具创建结构时遇到问题。每个命令可以有 n 个子命令,每个子命令可以有 n 个子命令。

我的问题是,在 Go 中,我正在努力寻找一种方法来创建递归函数来输出每个命令的名称,以及每个 n 子命令 + 每个 该子命令的 n 个子命令,在一个完整列表中。

例如,我希望得到以下输出:

1. command1
2. command2
3. command3
4. command3 subcommand1
5. command3 subcommand1 subcommand1
6. command3 subcommand2

这是我的代码:

package main

import (
    "fmt"
)

type command struct {
    name        string
    parent      *command
    subcommands []*command
}

func getLastCommand(c command) command {
    for _, s := range c.subcommands {
        if len(s.subcommands) == 0 {
            return *s
        }
        return getLastCommand(*s)
    }
    return c
}

func main() {
    cmdBase1 := command{
        name: "base1",
    }

    cmdBase2 := command{
        name: "base2",
    }

    var (
        cmdBase3,
        cmdBase3Sub1,
        cmdBase3Sub1Sub1,
        cmdBase3Sub2 command
    )

    cmdBase3 = command{
        name:        "base3",
        subcommands: []*command{&cmdBase3Sub1, &cmdBase3Sub2},
    }

    cmdBase3Sub1 = command{
        name:        "base3:sub1",
        parent:      &cmdBase3,
        subcommands: []*command{&cmdBase3Sub1Sub1},
    }

    cmdBase3Sub1Sub1 = command{
        name:   "base3:sub1:sub1",
        parent: &cmdBase3Sub1,
    }

    cmdBase3Sub2 = command{
        name:   "base3:sub2",
        parent: &cmdBase3,
    }

    // root commands
    commands := []command{
        cmdBase1,
        cmdBase2,
        cmdBase3,
    }

    for _, c := range commands {
        last := getLastCommand(c)
        fmt.Println(last.name)
    }
}

https://play.golang.org/p/HZPRlSghfAY

这是当前的输出:

base1
base2
base3:sub1:sub1

我想要的输出是上面的代码是:

base1
base2
base3
base3:sub1
base3:sub1:sub1
base3:sub2

我需要在我的代码中进行哪些更改才能获得上述所需的输出?有没有我可以遵循的算法或数据结构来解决这个问题?我尝试过深度优先和二分搜索,但似乎无法将其融入我的结构。

【问题讨论】:

    标签: go recursion struct slice


    【解决方案1】:

    一个简单而优雅的解决方案是使用print() 方法“武装”command。这可以打印它的名称,并覆盖它的子命令,调用它们的print()(它们做同样的事情):

    func (c *command) print() {
        fmt.Println(c.name)
        for _, sc := range c.subcommands {
            sc.print()
        }
    }
    

    然后在main() 中打印命令只是调用他们的print() 方法(甚至不需要/使用getLastCommand()):

    for _, c := range commands {
        c.print()
    }
    

    这将产生您想要的输出(在Go Playground 上尝试):

    base1
    base2
    base3
    base3:sub1
    base3:sub1:sub1
    base3:sub2
    

    请注意,print() 当然不一定是方法,它也可能是常规函数,在这种情况下,它可能如下所示:

    func print(c *command) {
        fmt.Println(c.name)
        for _, sc := range c.subcommands {
            print(sc)
        }
    }
    

    还有main()中的循环:

    for _, c := range commands {
        print(&c)
    }
    

    结果一样,在Go Playground上试试这个。

    我还建议保持一致。如果您决定使用指向command 的指针,请在任何地方使用(例如,main() 中的commands 切片存储非指针,这就是为什么必须将其元素的地址传递给print())。

    【讨论】:

    • 传奇!正是我想要做的。谢谢:)
    猜你喜欢
    • 1970-01-01
    • 2020-09-02
    • 2020-07-14
    • 2022-09-27
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    • 2018-11-19
    相关资源
    最近更新 更多