utils.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. package gse
  2. import (
  3. "bytes"
  4. "fmt"
  5. )
  6. // ToString segments to string 输出分词结果为字符串
  7. //
  8. // 有两种输出模式,以 "中华人民共和国" 为例
  9. //
  10. // 普通模式(searchMode=false)输出一个分词 "中华人民共和国/ns "
  11. // 搜索模式(searchMode=true) 输出普通模式的再细致切分:
  12. // "中华/nz 人民/n 共和/nz 国/n 共和国/ns 人民共和国/nt 中华人民共和国/ns "
  13. //
  14. // 默认 searchMode=false
  15. // 搜索模式主要用于给搜索引擎提供尽可能多的关键字,详情请见 Token 结构体的注释。
  16. func ToString(segs []Segment, searchMode ...bool) (output string) {
  17. var mode bool
  18. if len(searchMode) > 0 {
  19. mode = searchMode[0]
  20. }
  21. if mode {
  22. for _, seg := range segs {
  23. output += tokenToString(seg.token)
  24. }
  25. return
  26. }
  27. for _, seg := range segs {
  28. output += fmt.Sprintf("%s/%s ",
  29. textSliceToString(seg.token.text), seg.token.pos)
  30. }
  31. return
  32. }
  33. func tokenToBytes(token *Token) (output []byte) {
  34. for _, s := range token.segments {
  35. output = append(output, tokenToBytes(s.token)...)
  36. }
  37. output = append(output, []byte(fmt.Sprintf("%s/%s ",
  38. textSliceToString(token.text), token.pos))...)
  39. return
  40. }
  41. func tokenToString(token *Token) (output string) {
  42. hasOnlyTerminalToken := true
  43. for _, s := range token.segments {
  44. if len(s.token.segments) > 1 || IsJp(string(s.token.text[0])) {
  45. hasOnlyTerminalToken = false
  46. }
  47. if !hasOnlyTerminalToken {
  48. if s != nil {
  49. output += tokenToString(s.token)
  50. }
  51. }
  52. }
  53. output += fmt.Sprintf("%s/%s ", textSliceToString(token.text), token.pos)
  54. return
  55. }
  56. // ToSlice segments to slice 输出分词结果到一个字符串 slice
  57. //
  58. // 有两种输出模式,以 "中华人民共和国" 为例
  59. //
  60. // 普通模式(searchMode=false)输出一个分词"[中华人民共和国]"
  61. // 搜索模式(searchMode=true) 输出普通模式的再细致切分:
  62. // "[中华 人民 共和 国 共和国 人民共和国 中华人民共和国]"
  63. //
  64. // 默认 searchMode=false
  65. // 搜索模式主要用于给搜索引擎提供尽可能多的关键字,详情请见Token结构体的注释。
  66. func ToSlice(segs []Segment, searchMode ...bool) (output []string) {
  67. var mode bool
  68. if len(searchMode) > 0 {
  69. mode = searchMode[0]
  70. }
  71. if mode {
  72. for _, seg := range segs {
  73. output = append(output, tokenToSlice(seg.token)...)
  74. }
  75. return
  76. }
  77. for _, seg := range segs {
  78. output = append(output, seg.token.Text())
  79. }
  80. return
  81. }
  82. func tokenToSlice(token *Token) (output []string) {
  83. hasOnlyTerminalToken := true
  84. for _, s := range token.segments {
  85. if len(s.token.segments) > 1 || IsJp(string(s.token.text[0])) {
  86. hasOnlyTerminalToken = false
  87. }
  88. if !hasOnlyTerminalToken {
  89. output = append(output, tokenToSlice(s.token)...)
  90. }
  91. }
  92. output = append(output, textSliceToString(token.text))
  93. return output
  94. }
  95. // 将多个字元拼接一个字符串输出
  96. func textToString(text []Text) string {
  97. var output string
  98. for _, word := range text {
  99. output += string(word)
  100. }
  101. return output
  102. }
  103. // 将多个字元拼接一个字符串输出
  104. func textSliceToString(text []Text) string {
  105. return Join(text)
  106. }
  107. // 返回多个字元的字节总长度
  108. func textSliceByteLen(text []Text) (length int) {
  109. for _, word := range text {
  110. length += len(word)
  111. }
  112. return
  113. }
  114. func textSliceToBytes(text []Text) []byte {
  115. var buf bytes.Buffer
  116. for _, word := range text {
  117. buf.Write(word)
  118. }
  119. return buf.Bytes()
  120. }
  121. // Join is better string splicing
  122. func Join(text []Text) string {
  123. switch len(text) {
  124. case 0:
  125. return ""
  126. case 1:
  127. return string(text[0])
  128. case 2:
  129. // Special case for common small values.
  130. // Remove if github.com/golang/go/issues/6714 is fixed
  131. return string(text[0]) + string(text[1])
  132. case 3:
  133. // Special case for common small values.
  134. // Remove if #6714 is fixed
  135. return string(text[0]) + string(text[1]) + string(text[2])
  136. }
  137. n := 0
  138. for i := 0; i < len(text); i++ {
  139. n += len(text[i])
  140. }
  141. b := make([]byte, n)
  142. bp := copy(b, text[0])
  143. for _, str := range text[1:] {
  144. bp += copy(b[bp:], str)
  145. }
  146. return string(b)
  147. }