【问题标题】:Check if a value is in a list检查一个值是否在列表中
【发布时间】:2015-05-26 07:41:21
【问题描述】:

Go 是否有类似于 Python 的 in 关键字的东西?我想检查一个值是否在列表中。

例如在 Python 中:

x = 'red'

if x in ['red', 'green', 'yellow', 'blue']:
    print "found"
else:
    print "not found"

在 Go 中,我想出了使用 set idiom,但我认为这并不理想,因为我必须指定一个我没有使用的 int 值。

x := "red"

valid := map[string]int{"red": 0, "green": 0,"yellow": 0, "blue": 0}

if _, ok := valid[x]; ok {
    fmt.Println("found")
} else {
    fmt.Println("not found")
}

我知道有一个in 关键字可能与泛型有关。有没有办法使用 go generate 或其他东西来做到这一点?

【问题讨论】:

标签: dictionary go set


【解决方案1】:

您可以将map[string]bool 用作一组。当测试并且某个键不在映射中时,将返回 bool 的零值,即 false。

所以用有效值作为键和true 作为值填充映射。如果测试的键值在映射中,则其存储的true 值将是结果。如果测试的键值不在映射中,则返回值类型的零值,即false。

使用它,测试变得如此简单:

valid := map[string]bool{"red": true, "green": true, "yellow": true, "blue": true}

if valid[x] {
    fmt.Println("found")
} else {
    fmt.Println("not found")
}

在Go Playground 上试试(使用下面提到的变体)。

这在博文中有提到:Go maps in action: Exploiting zero values

注意:

如果您有许多有效值,由于要存储在映射中的所有值都是true,因此使用切片列出有效值并使用for range 循环来初始化您的映射可能更紧凑,类似这样:

for _, v := range []string{"red", "green", "yellow", "blue"} {
    valid[v] = true
}

注意 #2:

如果您不想使用for range 循环初始化,您仍然可以通过创建一个无类型(或bool-typed)单字母const 来稍微优化它:

const t = true
valid := map[string]bool{"red": t, "green": t, "yellow": t, "blue": t}

【讨论】:

  • 对于大型集合,使用 map[string]struct{} 而不是 map[string]bool 可能会节省空间,因为空结构占用零空间。存在性测试需要使用二值形式_, exists := valid[x]。首先使用空结构文字 {} 而不是 bool true 创建地图。
【解决方案2】:

我认为另一个答案中的map[string]bool 是一个不错的选择。另一种方法 是map[string]struct{},它使用的内存略少:

package main

func main() {
   x, valid := "red", map[string]struct{}{
      "red": {}, "green": {}, "yellow": {}, "blue": {},
   }
   if _, ok := valid[x]; ok {
      println("found")
   } else {
      println("not found")
   }
}

你也可以把它包装成一个类型:

package main

type set map[string]struct{}

func newSet(slice []string) set {
   s := make(set)
   for _, each := range slice {
      s[each] = struct{}{}
   }
   return s
}

func (s set) has(v string) bool {
   _, ok := s[v]
   return ok
}

func main() {
   x := "red"
   if newSet([]string{"red", "green", "yellow", "blue"}).has(x) {
      println("found")
   } else {
      println("not found")
   }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-18
    • 2011-02-10
    • 1970-01-01
    • 2019-12-11
    • 2020-05-11
    • 2014-01-30
    • 2015-06-20
    相关资源
    最近更新 更多