使用Golang如何从表格创建一棵树?

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

make a tree from a table using golang?

问题

我想从一个表格中创建一棵树。表格如下所示:

  1. OrgID OrgName parentID
  2. A001 Dept 0 -----顶级
  3. A002 subDept1 A001
  4. A003 sub_subDept A002
  5. A006 gran_subDept A003
  6. A004 subDept2 A001

我希望结果如下所示,使用Go语言如何实现:

<pre>
Dept

--subDept1

----sub_subDept

------gran_subDept

--subDept2
</pre>

英文:

I want to make a tree from a table.
the table is as following:

  1. OrgID OrgName parentID
  2. A001 Dept 0 -----th top
  3. A002 subDept1 A001
  4. A003 sub_subDept A002
  5. A006 gran_subDept A003
  6. A004 subDept2 A001

and i want the result is as following,how to do it using go:
<pre>
Dept

--subDept1

----sub_subDept

------gran_subDept

--subDept2
</pre>

答案1

得分: 10

如果你想将这些行解析为树结构,可以按照以下方式进行:

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "io"
  6. "os"
  7. "strings"
  8. )
  9. type Node struct {
  10. name string
  11. children []*Node
  12. }
  13. var (
  14. nodeTable = map[string]*Node{}
  15. root *Node
  16. )
  17. func add(id, name, parentId string) {
  18. fmt.Printf("add: id=%v name=%v parentId=%v\n", id, name, parentId)
  19. node := &Node{name: name, children: []*Node{}}
  20. if parentId == "0" {
  21. root = node
  22. } else {
  23. parent, ok := nodeTable[parentId]
  24. if !ok {
  25. fmt.Printf("add: parentId=%v: not found\n", parentId)
  26. return
  27. }
  28. parent.children = append(parent.children, node)
  29. }
  30. nodeTable[id] = node
  31. }
  32. func scan() {
  33. input := os.Stdin
  34. reader := bufio.NewReader(input)
  35. lineCount := 0
  36. for {
  37. lineCount++
  38. line, err := reader.ReadString('\n')
  39. if err == io.EOF {
  40. break
  41. }
  42. if err != nil {
  43. fmt.Printf("error reading lines: %v\n", err)
  44. return
  45. }
  46. tokens := strings.Fields(line)
  47. if t := len(tokens); t != 3 {
  48. fmt.Printf("bad input line %v: tokens=%d [%v]\n", lineCount, t, line)
  49. continue
  50. }
  51. add(tokens[0], tokens[1], tokens[2])
  52. }
  53. }
  54. func showNode(node *Node, prefix string) {
  55. if prefix == "" {
  56. fmt.Printf("%v\n\n", node.name)
  57. } else {
  58. fmt.Printf("%v %v\n\n", prefix, node.name)
  59. }
  60. for _, n := range node.children {
  61. showNode(n, prefix+"--")
  62. }
  63. }
  64. func show() {
  65. if root == nil {
  66. fmt.Printf("show: root node not found\n")
  67. return
  68. }
  69. fmt.Printf("RESULT:\n")
  70. showNode(root, "")
  71. }
  72. func main() {
  73. fmt.Printf("main: reading input from stdin\n")
  74. scan()
  75. fmt.Printf("main: reading input from stdin -- done\n")
  76. show()
  77. fmt.Printf("main: end\n")
  78. }
英文:

If you want to parse the lines into a tree structure, this is a way to do it:

  1. package main
  2. import (
  3. &quot;bufio&quot;
  4. &quot;fmt&quot;
  5. &quot;io&quot;
  6. &quot;os&quot;
  7. &quot;strings&quot;
  8. )
  9. type Node struct {
  10. name string
  11. children []*Node
  12. }
  13. var (
  14. nodeTable = map[string]*Node{}
  15. root *Node
  16. )
  17. func add(id, name, parentId string) {
  18. fmt.Printf(&quot;add: id=%v name=%v parentId=%v\n&quot;, id, name, parentId)
  19. node := &amp;Node{name: name, children: []*Node{}}
  20. if parentId == &quot;0&quot; {
  21. root = node
  22. } else {
  23. parent, ok := nodeTable[parentId]
  24. if !ok {
  25. fmt.Printf(&quot;add: parentId=%v: not found\n&quot;, parentId)
  26. return
  27. }
  28. parent.children = append(parent.children, node)
  29. }
  30. nodeTable[id] = node
  31. }
  32. func scan() {
  33. input := os.Stdin
  34. reader := bufio.NewReader(input)
  35. lineCount := 0
  36. for {
  37. lineCount++
  38. line, err := reader.ReadString(&#39;\n&#39;)
  39. if err == io.EOF {
  40. break
  41. }
  42. if err != nil {
  43. fmt.Printf(&quot;error reading lines: %v\n&quot;, err)
  44. return
  45. }
  46. tokens := strings.Fields(line)
  47. if t := len(tokens); t != 3 {
  48. fmt.Printf(&quot;bad input line %v: tokens=%d [%v]\n&quot;, lineCount, t, line)
  49. continue
  50. }
  51. add(tokens[0], tokens[1], tokens[2])
  52. }
  53. }
  54. func showNode(node *Node, prefix string) {
  55. if prefix == &quot;&quot; {
  56. fmt.Printf(&quot;%v\n\n&quot;, node.name)
  57. } else {
  58. fmt.Printf(&quot;%v %v\n\n&quot;, prefix, node.name)
  59. }
  60. for _, n := range node.children {
  61. showNode(n, prefix+&quot;--&quot;)
  62. }
  63. }
  64. func show() {
  65. if root == nil {
  66. fmt.Printf(&quot;show: root node not found\n&quot;)
  67. return
  68. }
  69. fmt.Printf(&quot;RESULT:\n&quot;)
  70. showNode(root, &quot;&quot;)
  71. }
  72. func main() {
  73. fmt.Printf(&quot;main: reading input from stdin\n&quot;)
  74. scan()
  75. fmt.Printf(&quot;main: reading input from stdin -- done\n&quot;)
  76. show()
  77. fmt.Printf(&quot;main: end\n&quot;)
  78. }

答案2

得分: 5

根据你的问题和评论提供的信息,可以解决你的问题的是一个普通的递归循环。

  1. package main
  2. import "fmt"
  3. type Org struct {
  4. OrgID string
  5. OrgName string
  6. parentID string
  7. }
  8. func printTree(tbl []Org, parent string, depth int) {
  9. for _, r := range tbl {
  10. if r.parentID == parent {
  11. for i := 0; i < depth; i++ {
  12. fmt.Print("--")
  13. }
  14. fmt.Print(r.OrgName, "\n\n")
  15. printTree(tbl, r.OrgID, depth+1)
  16. }
  17. }
  18. }
  19. func main() {
  20. data := []Org{
  21. {"A001", "Dept", "0 -----th top"},
  22. {"A002", "subDept1", "A001"},
  23. {"A003", "sub_subDept", "A002"},
  24. {"A006", "gran_subDept", "A003"},
  25. {"A004", "subDept2", "A001"},
  26. }
  27. printTree(data, "0 -----th top", 0)
  28. }

结果:

  1. Dept
  2. --subDept1
  3. ----sub_subDept
  4. ------gran_subDept
  5. --subDept2

Playground: http://play.golang.org/p/27CQAhI8gf

请注意,如果父级是其自己子级的后代,这个递归函数可能会陷入循环中。

英文:

With the information provided in your question and comment, what could solve your problem is an ordinary recursive loop.

  1. package main
  2. import &quot;fmt&quot;
  3. type Org struct {
  4. OrgID string
  5. OrgName string
  6. parentID string
  7. }
  8. func printTree(tbl []Org, parent string, depth int) {
  9. for _, r := range tbl {
  10. if r.parentID == parent {
  11. for i := 0; i &lt; depth; i++ {
  12. fmt.Print(&quot;--&quot;)
  13. }
  14. fmt.Print(r.OrgName, &quot;\n\n&quot;)
  15. printTree(tbl, r.OrgID, depth+1)
  16. }
  17. }
  18. }
  19. func main() {
  20. data := []Org{
  21. {&quot;A001&quot;, &quot;Dept&quot;, &quot;0 -----th top&quot;},
  22. {&quot;A002&quot;, &quot;subDept1&quot;, &quot;A001&quot;},
  23. {&quot;A003&quot;, &quot;sub_subDept&quot;, &quot;A002&quot;},
  24. {&quot;A006&quot;, &quot;gran_subDept&quot;, &quot;A003&quot;},
  25. {&quot;A004&quot;, &quot;subDept2&quot;, &quot;A001&quot;},
  26. }
  27. printTree(data, &quot;0 -----th top&quot;, 0)
  28. }

Result:

  1. Dept
  2. --subDept1
  3. ----sub_subDept
  4. ------gran_subDept
  5. --subDept2

Playground: http://play.golang.org/p/27CQAhI8gf

Be aware that this recursive function might get stuck in an loop incase there if a parent is the descendant of its own child.

huangapple
  • 本文由 发表于 2014年4月9日 17:02:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/22957638.html
匿名

发表评论

匿名网友

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

确定