Go中检查字符串切片是否包含某个值

问题描述 投票:0回答:4

检查某个值是否在字符串切片中的最佳方法是什么?我会在其他语言中使用 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
4个回答
66
投票

如果您有一个任意顺序的字符串切片,则查找切片中是否存在某个值需要 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")

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


20
投票

要更换套件,您应该使用

map[string]struct{}
。这是有效的并且被认为是惯用的,“值”绝对不占用空间。

初始化设置:

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

放置物品:

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

检查物品是否存在:

_, isPresent := set["item"]

删除项目:

delete(set, "item")

4
投票

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

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 包,因此您可以对切片进行排序和二分搜索


0
投票

在 Go 1.21 及更高版本中,您可以使用 slices#Contains:

list := []string{"a", "b", "x"}
fmt.Println(slices.Contains(list, "b")) // true
fmt.Println(slices.Contains(list, "z")) // false

(参见 https://go.dev/play/p/2ycquYNfLGR 在 Go Playground 中运行此示例)

© www.soinside.com 2019 - 2024. All rights reserved.