父子关系结构梳理(Golang实现)
2016.11.24 15:13:09

练练Golang,把一个数据库表中常用的两列父子关系结构(如下表)梳理成了目录形式:

  P      C
------------
'A'  | 'A1'
'A'  | 'A2'
'A1' | 'A11'
'A2' | 'A21'
'A2' | 'A22'
...  | ...

发现所用代码比Python版多了30%。

顺便谈谈对Golang的感觉,Golang的开发哲学还是比较独树一帜的,比如为啥没有参数默认值、泛型等,都有它自己的理解;而它的一些语法,如结构体、接口、panic设计、命名返回等,也是比较另辟蹊径,刚开始确实有个熟悉及适应的过程。

遵循“Simplify only after the function is correct”,先把功能实现了,以后把Golang理解得更加透彻了、更有Go味儿了,再回头审视一下。

附上Golang代码:

package main

import (
    "fmt"
    "strings"
)

type node struct {
    name  string
    child []*node
}

func getTopElements(o [][2]string,
    fn func([]string, string) bool) (t []string, anyLuck bool) {
    for _, elem1 := range o {
        isFound := false
        for _, elem2 := range o {
            if elem1[0] == elem2[1] {
                isFound = true
                break
            }
        }
        if !isFound {
            anyLuck = true
            if !fn(t, elem1[0]) {
                t = append(t, elem1[0])
            }
        }
    }
    return
}

func seek(root *node, origin [][2]string) {
    searchingNode := root.child
    for {
        endFlag := true
        tmpNode := []*node{}

        for _, item := range searchingNode {
            for _, o := range origin {
                if item.name == o[0] {
                    endFlag = false
                    item.child = append(item.child, &node{name: o[1]})
                }
            }
            for _, child := range item.child {
                tmpNode = append(tmpNode, child)
            }
        }
        if endFlag {
            break
        } else {
            searchingNode = tmpNode
        }
    }
}

func genPrintTree(n *node, indent int, s []string) []string {
    for _, item := range n.child {
        s = genPrintTree(item, indent+1, s)
    }
    s = append(s, strings.Repeat("  ", indent-1)+"  ."+n.name)
    return s
}

func printTree(n *node, indent int, s []string) {
    sc := genPrintTree(n, indent, s)
    for idx := range sc {
        fmt.Printf("%v\n", sc[len(sc)-1-idx])
    }
}

func main() {
    origin := [][2]string{
        {"A112", "A1122"},
        {"A", "A1"},
        {"A", "A2"},
        {"A1", "A11"},
        {"A2", "A21"},
        {"A2", "A22"},
        {"A", "A3"},
        {"A22", "A221"},
        {"A11", "A111"},
        {"A21", "A211"},
        {"A11", "A112"},
        {"A21", "A212"},
        {"A11", "A113"},
        {"A112", "A1121"},
        {"A3", "A31"},
        {"A31", "A311"},
        {"A22", "A222"},
        {"A31", "A312"},
        {"A31", "A313"},
        {"A311", "A3111"},
        {"A312", "A3121"},
        {"A3111", "A31111"},
        {"B", "B1"},
        {"B", "B2"},
        {"B2", "B21"},
        {"C", "C1"},
        {"C1", "C11"},
        {"C11", "C111"},
        {"C11", "C112"},
        {"C112", "C1121"},
        {"C1121", "C11211"},
        {"C11", "C113"},
        {"C11211", "C112111"},
        {"C112111", "C1121111"},
        {"B21", "B211"},
        {"C", "C2"},
        {"C2", "C21"},
        {"C21", "C22"},
        {"C", "C3"},
        {"B1", "B11"}}

    root := &node{name: "root"}

    if topElements, anyLuck := getTopElements(origin,
        func(t []string, e string) (isExist bool) {
            for _, item := range t {
                if item == e {
                    isExist = true
                    break
                }
            }
            return
        }); anyLuck {
        for _, item := range topElements {
            root.child = append(root.child, &node{name: item})
        }
        seek(root, origin)
    }

    printTree(root, 1, []string{})
}

运行结果:

  .root
    .C
      .C3
      .C2
        .C21
          .C22
      .C1
        .C11
          .C113
          .C112
            .C1121
              .C11211
                .C112111
                  .C1121111
          .C111
    .B
      .B2
        .B21
          .B211
      .B1
        .B11
    .A
      .A3
        .A31
          .A313
          .A312
            .A3121
          .A311
            .A3111
              .A31111
      .A2
        .A22
          .A222
          .A221
        .A21
          .A212
          .A211
      .A1
        .A11
          .A113
          .A112
            .A1121
            .A1122
          .A111

继续Golang之旅——并发。


(2)

发表评论请先登录或注册