Guest User

Untitled

a guest
Nov 20th, 2017
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.06 KB | None | 0 0
  1. package main
  2.  
  3. import (
  4. "os"
  5. "bufio"
  6. "io"
  7. "bytes"
  8. "fmt"
  9. "errors"
  10. "strconv"
  11. "strings"
  12. )
  13.  
  14. const (
  15. rootNodeName = "this is the root node name, which is must not be used in real data"
  16. wildCardName = "*"
  17. delim = 29
  18. )
  19.  
  20. // Analyzer analysis and store the path, can return the path pattern
  21. type Analyzer = *Node
  22.  
  23. // NewAnalyzer create a new Analyzer
  24. func NewAnalyzer(maxLeaf int) Analyzer {
  25. return &Node{
  26. name: rootNodeName,
  27. deep: 0,
  28. maxLeaf: maxLeaf,
  29. children: make([]*Node, 0, maxLeaf),
  30. }
  31. }
  32.  
  33. func Load(file string, maxLeaf int) (Analyzer, error) {
  34. f, err := os.Open(file)
  35. if err != nil {
  36. return nil, err
  37. }
  38. defer f.Close()
  39. reader := bufio.NewReader(f)
  40. data := make([]string, 0, 10000)
  41. for {
  42. item, err := reader.ReadBytes(delim);
  43. if err != nil && err != io.EOF{
  44. return nil, err
  45. }
  46. if len(item) > 0 {
  47. data = append(data, string(item[:len(item)-1]))
  48. }
  49. if err == io.EOF {
  50. break
  51. }
  52. }
  53. return load(data, maxLeaf)
  54. }
  55.  
  56. func (analyzer Analyzer) Apply(items []string) []string {
  57. node := analyzer
  58. for _, item := range items {
  59. if item == "" {
  60. continue
  61. }
  62. item := item
  63. node = node.addChildIfNotExist(node.newChild(item))
  64. }
  65. return node.path()
  66. }
  67.  
  68. func (analyzer Analyzer) patternOf(items []string) []string {
  69. node := analyzer
  70. fields := make([]string, 0, len(items))
  71. for _, item := range items {
  72. item := item
  73. matched := false
  74. for _, n := range node.children {
  75. if n.name == item || n.name == wildCardName {
  76. fields = append(fields, n.name)
  77. matched = true
  78. }
  79. }
  80. if !matched {
  81. return items
  82. }
  83. }
  84. return fields
  85. }
  86.  
  87. func (analyzer Analyzer) Dump(file string) ( error){
  88. f, err := os.Create(file)
  89. if err != nil {
  90. return err
  91. }
  92. defer f.Close()
  93. data := make([]string, 0, 10000)
  94. buf := bytes.NewBuffer(nil)
  95. for _, item := range analyzer.dump(data, -1) {
  96. if _, err := buf.WriteString(item); err != nil {
  97. return err
  98. }
  99. if err := buf.WriteByte(delim); err != nil {
  100. return err
  101. }
  102. }
  103. _, err = io.Copy(f, buf)
  104. return err
  105. }
  106.  
  107.  
  108. // Node represents a leaf in analyzer tree
  109. type Node struct {
  110. name string
  111. deep int
  112. maxLeaf int
  113. parent *Node
  114. children []*Node
  115. }
  116.  
  117. func (node *Node) addChildIfNotExist(child *Node) *Node {
  118. for _, n := range node.children {
  119. if n.name == child.name || n.name == wildCardName {
  120. // 重名节点已存在, 将自己的儿子节点交给它
  121. for _, c := range child.children {
  122. c := c
  123. n.addChildIfNotExist(c)
  124. }
  125. return n
  126. }
  127. }
  128. // 超出最大节点数, 合并
  129. if len(node.children) >= node.maxLeaf {
  130. node.mergeChildren()
  131. return node.children[0]
  132. }
  133. node.children = append(node.children, child)
  134. return child
  135. }
  136.  
  137. func (node *Node) newChild(name string) *Node {
  138. return &Node{
  139. name: name,
  140. parent: node,
  141. children: make([]*Node, 0, node.maxLeaf),
  142. maxLeaf: node.maxLeaf,
  143. deep: node.deep + 1,
  144. }
  145. }
  146.  
  147. func (node *Node) mergeChildren() *Node {
  148. newNode := node.newChild(wildCardName)
  149.  
  150. // 该节点的所有子节点, 都要归并成一个通配节点, 而这些子节点的子节点, 都要加到新的通配节点上.
  151. for _, child := range node.children {
  152. for _, child2 := range child.children {
  153. newNode.addChildIfNotExist(child2)
  154. }
  155. }
  156. node.children = []*Node{newNode}
  157. return newNode
  158. }
  159.  
  160. func (node *Node) isRoot() bool {
  161. return node.name == rootNodeName
  162. }
  163.  
  164. func (node *Node) path() []string {
  165. fields := make([]string, node.deep)
  166. i := node.deep - 1
  167. for node != nil && !node.isRoot() {
  168. fields[i] = node.name
  169. i--
  170. node = node.parent
  171. }
  172. return fields
  173. }
  174.  
  175. func (node *Node) dump(data []string, parentIndex int) []string {
  176. data = append(data, node.name, fmt.Sprintf("%d", parentIndex))
  177. index := len(data) - 2
  178. for _, child := range node.children {
  179. data = child.dump(data, index)
  180. }
  181. return data
  182. }
  183.  
  184. func load(data []string, maxLeaf int) (*Node, error){
  185. if len(data) < 2 {
  186. return nil, errors.New("data is too short")
  187. }
  188. nodes := make([]*Node, 0, len(data))
  189. for i, item := range data {
  190. var node *Node
  191. if i % 2 == 0 {
  192. pi, err := strconv.Atoi(data[i+1])
  193. if err != nil {
  194. return nil, fmt.Errorf("\"%s\" at index %d is not a number", data[i+1], i+1)
  195. }
  196. if pi == -1 { // root node
  197. node = &Node{
  198. name: item,
  199. deep: 0,
  200. maxLeaf: maxLeaf,
  201. }
  202. } else {
  203. node = &Node{
  204. name: item,
  205. parent: nodes[pi],
  206. maxLeaf: maxLeaf,
  207. }
  208. node.deep = node.parent.deep + 1
  209. node.parent.children = append(node.parent.children, node)
  210. }
  211. }
  212. nodes = append(nodes, node)
  213. }
  214. return nodes[0], nil
  215. }
  216.  
  217. func main() {
  218.  
  219. paths := []string{
  220. "a/b/c/d",
  221. "a/w/c/d",
  222. "a/l/c/d",
  223. "a/d/i/d",
  224. "a/1/i/d",
  225. "a/8/j/d",
  226. "a/9/j/d",
  227. "z/4/k/f",
  228. "",
  229. "/",
  230. "a",
  231. }
  232.  
  233. analyzer := NewAnalyzer(3)
  234.  
  235. for _, path := range paths {
  236. fields := strings.Split(path, "/")
  237. result := analyzer.Apply(fields)
  238. fmt.Println(path, "=>", strings.Join(result, "/"))
  239. }
  240. result := analyzer.Apply(nil)
  241. fmt.Println("<nil> =>", strings.Join(result, "/"))
  242. result = analyzer.Apply([]string{})
  243. fmt.Println("<empty> =>", strings.Join(result, "/"))
  244.  
  245. if err := analyzer.Dump("/tmp/data"); err != nil {
  246. panic(err)
  247. }
  248.  
  249. analyzer, err := Load("/tmp/data", 3)
  250. if err != nil {
  251. panic(err)
  252. }
  253. }
Add Comment
Please, Sign In to add comment