Go 集合功能

我们经常需要程序去处理一些集合数据,比如选出所有符合条件的数据或者使用一个自定义函数将一个集合元素拷贝到另外一个集合。

在一些语言里面,通常是使用泛化数据结构或者算法。但是Go不支持泛化类型,在Go里面如果你的程序或者数据类型需要操作集合,那么通常是为集合提供一些操作函数。

这里演示了一些操作strings切片的集合函数,你可以使用这些例子来构建你自己的函数。注意在有些情况下,使用内联集合操作代码会更清晰,而不是去创建新的帮助函数。

  1. package main
  2. import "strings"
  3. import "fmt"
  4. // 返回t在vs中第一次出现的索引,如果没有找到t,返回-1
  5. func Index(vs []string, t string) int {
  6. for i, v := range vs {
  7. if v == t {
  8. return i
  9. }
  10. }
  11. return -1
  12. }
  13. // 如果t存在于vs中,那么返回true,否则false
  14. func Include(vs []string, t string) bool {
  15. return Index(vs, t) >= 0
  16. }
  17. // 如果使用vs中的任何一个字符串作为函数f的参数可以让f返回true,
  18. // 那么返回true,否则false
  19. func Any(vs []string, f func(string) bool) bool {
  20. for _, v := range vs {
  21. if f(v) {
  22. return true
  23. }
  24. }
  25. return false
  26. }
  27. // 如果分别使用vs中所有的字符串作为f的参数都能让f返回true,
  28. // 那么返回true,否则返回false
  29. func All(vs []string, f func(string) bool) bool {
  30. for _, v := range vs {
  31. if !f(v) {
  32. return false
  33. }
  34. }
  35. return true
  36. }
  37. // 返回一个新的字符串切片,切片的元素为vs中所有能够让函数f
  38. // 返回true的元素
  39. func Filter(vs []string, f func(string) bool) []string {
  40. vsf := make([]string, 0)
  41. for _, v := range vs {
  42. if f(v) {
  43. vsf = append(vsf, v)
  44. }
  45. }
  46. return vsf
  47. }
  48. // 返回一个bool类型切片,切片的元素为vs中所有字符串作为f函数
  49. // 参数所返回的结果
  50. func Map(vs []string, f func(string) string) []string {
  51. vsm := make([]string, len(vs))
  52. for i, v := range vs {
  53. vsm[i] = f(v)
  54. }
  55. return vsm
  56. }
  57. func main() {
  58. // 来,试试我们的字符串切片操作函数
  59. var strs = []string{"peach", "apple", "pear", "plum"}
  60. fmt.Println(Index(strs, "pear"))
  61. fmt.Println(Include(strs, "grape"))
  62. fmt.Println(Any(strs, func(v string) bool {
  63. return strings.HasPrefix(v, "p")
  64. }))
  65. fmt.Println(All(strs, func(v string) bool {
  66. return strings.HasPrefix(v, "p")
  67. }))
  68. fmt.Println(Filter(strs, func(v string) bool {
  69. return strings.Contains(v, "e")
  70. }))
  71. // 上面的例子都使用匿名函数,你也可以使用命名函数
  72. fmt.Println(Map(strs, strings.ToUpper))
  73. }

运行结果

  1. 2
  2. false
  3. true
  4. false
  5. [peach apple pear]
  6. [PEACH APPLE PEAR PLUM]