【问题标题】:Check whether a string slice contains a certain value in Go检查字符串切片是否包含 Go 中的某个值
【发布时间】:2012-11-11 06:56:14
【问题描述】:

检查某个值是否在字符串切片中的最佳方法是什么?我会使用其他语言的 Set,但 Go 没有。

到目前为止,我最好的尝试是:

package main

import "fmt"

func main() {
    list := []string{"a", "b", "x"}
    fmt.Println(isValueInList("b", list))
    fmt.Println(isValueInList("z", list))
}

func isValueInList(value string, list []string) bool {
    for _, v := range list {
        if v == value {
            return true
        }
    }
    return false
}

http://play.golang.org/p/gkwMz5j09n

这个方案对于小切片应该没问题,但是对于元素多的切片怎么办?

【问题讨论】:

    标签: set go slice


    【解决方案1】:

    如果您有一个任意顺序的字符串切片,则查找切片中是否存在值需要 O(n) 时间。这适用于所有语言。

    如果您打算一遍又一遍地进行搜索,您可以使用其他数据结构来加快查找速度。但是,构建这些结构至少需要 O(n) 时间。因此,只有多次使用数据结构进行查找才能获得好处。

    例如,您可以将字符串加载到地图中。然后查找将花费 O(1) 时间。插入也需要 O(1) 时间,使得初始构建需要 O(n) 时间:

    set := make(map[string]bool)
    for _, v := range list {
        set[v] = true
    }
    
    fmt.Println(set["b"])
    

    您还可以对字符串切片进行排序,然后进行二分搜索。二进制搜索发生在 O(log(n)) 时间内。构建可能需要 O(n*log(n)) 时间。

    sort.Strings(list)
    i := sort.SearchStrings(list, "b")
    fmt.Println(i < len(list) && list[i] == "b")
    

    虽然理论上给定无限数量的值,但映射更快,但实际上搜索排序列表很可能会更快。您需要自己进行基准测试。

    【讨论】:

      【解决方案2】:

      要替换集合,您应该使用map[string]struct{}。这是有效的并且被认为是惯用的,“价值观”绝对不占空间。

      初始化集合:

      set := make(map[string]struct{})
      

      放一个物品:

      set["item"]=struct{}{}
      

      检查项目是否存在:

      _, isPresent := set["item"]
      

      删除一个项目:

      delete(set, "item")
      

      【讨论】:

        【解决方案3】:

        您可以使用地图,并具有价值,例如一个布尔值

        m := map[string] bool {"a":true, "b":true, "x":true}
        if m["a"] { // will be false if "a" is not in the map
            //it was in the map
        }
        

        还有 sort 包,因此您可以对切片进行排序和二进制搜索

        【讨论】:

        • 请注意,您不必使用 bool 虚拟值。您可以使用这样的空结构:map[string]struct{}.
        • 只是为了澄清@nemo 所说的,使用 struct{} 作为值的优点是它不占用内存。
        • "它不占用内存" ...对于值,当然映射仍然占用内存用于键和哈希表(或任何实现),它只是最小化映射使用的内存(在需要if _, ok := map["a"]; ok 样式检查而不是if map["a"] 的费用)。
        猜你喜欢
        • 1970-01-01
        • 2021-10-27
        • 2022-01-02
        • 1970-01-01
        • 2016-08-09
        • 2019-08-05
        • 1970-01-01
        • 1970-01-01
        • 2018-05-01
        相关资源
        最近更新 更多