首页 文章

如何检查 Map 中是否包含密钥?

提问于
浏览
493

我知道我可以迭代一张 Map 了,

for k, v := range m { ... }

并寻找一个关键但是有一种更有效的方法来测试一个关键字's existence in a map? Thanks. I couldn'在_129046中找到答案 .

10 回答

  • 4

    这里更好的方式

    if _, ok := dict["foo"]; ok {
        //do something here
    }
    
  • 8
    var empty struct{}
        var ok bool
        var m map[string]struct{}
        m = make(map[string]struct{})
        m["somestring"] = empty
    
    
        _, ok = m["somestring"]
        fmt.Println("somestring exists?", ok) 
        _, ok = m["not"]
        fmt.Println("not exists?", ok)
    

    那么,去运行maps.go somestring存在?真的不存在?假

  • -14

    go-nuts email list上搜索并找到了Peter Froehlich在11/15/2009发布的解决方案 .

    package main
    
    import "fmt"
    
    func main() {
            dict := map[string]int {"foo" : 1, "bar" : 2}
            value, ok := dict["baz"]
            if ok {
                    fmt.Println("value: ", value)
            } else {
                    fmt.Println("key not found")
            }
    }
    

    或者,更紧凑,

    if value, ok := dict["baz"]; ok {
        fmt.Println("value: ", value)
    } else {
        fmt.Println("key not found")
    }
    

    注意,使用 if 语句的这种形式, valueok 变量仅在 if 条件内可见 .

  • 90

    简答

    _, exists := timeZone[tz]    // Just checks for key existence
    val, exists := timeZone[tz]  // Checks for key existence and retrieves the value
    

    示例

    这是example at the Go Playground .

    更长的答案

    根据Effective GoMaps部分:

    尝试使用 Map 中不存在的键获取 Map 值将返回 Map 中条目类型的零值 . 例如,如果 Map 包含整数,则查找不存在的键将返回0.有时您需要区分缺失的条目和零值 . 是否有“UTC”的条目,或者是空字符串,因为它根本不在 Map 中?您可以区分多种分配形式 . var seconds int
    var ok bool
    秒,ok = timeZone [tz]
    出于显而易见的原因,这被称为“逗号确定”成语 . 在这个例子中,如果存在tz,则将适当地设置秒并且ok将为真;如果没有,秒将被设置为零,ok将为false . 这是一个将错误报告放在一起的函数:func offset(tz string)int {
    if seconds,ok:= timeZone [tz];好 {
    返回秒
    }
    log.Println(“未知时区:”,tz)
    返回0
    }
    要在 Map 中测试是否存在而不必担心实际值,可以使用空白标识符(_)代替值的常用变量 . _,present:= timeZone [tz]

  • 39

    一行答案:

    if val, ok := dict["foo"]; ok {
        //do something here
    }
    

    说明:

    Go中的 if 语句可以包括条件和初始化语句 . 上面的例子使用了两个:

    • 初始化两个变量 - val 将从 Map 接收"foo"的值或"zero value"(在这种情况下为空字符串)和 ok 将接收将被设置为 true 的布尔值,如果"foo"实际存在于 Map 中

    • 评估 ok ,如果"foo"在 Map 中,则为 true

    如果"foo"确实存在于 Map 中,则将执行 if 语句的正文, val 将是该范围的本地 .

  • 936

    如其他答案所述,一般解决方案是在特殊形式的assignment中使用index expression

    v, ok = a[x]
    v, ok := a[x]
    var v, ok = a[x]
    var v, ok T = a[x]
    

    这很干净 . 但它有一些限制:它必须是特殊形式的赋值 . 右侧表达式必须只是映射索引表达式,左侧表达式列表必须包含2个操作数,第一个值类型可赋值,第二个值可分配给 bool 值 . 此特殊表单索引表达式的结果的第一个值将是与键关联的值,第二个值将指示映射中是否存在具有给定键的条目(如果键存在于映射中) . 如果不需要其中一个结果,则左侧表达式列表也可能包含blank identifier .

    重要的是要知道,如果索引的映射值是 nil 或不包含键,则索引表达式将计算为映射的值类型的zero value . 例如:

    m := map[int]string{}
    s := m[1] // s will be the empty string ""
    var m2 map[int]float64 // m2 is nil!
    f := m2[2] // f will be 0.0
    
    fmt.Printf("%q %f", s, f) // Prints: "" 0.000000
    

    试试Go Playground .

    因此,如果我们知道我们不在 Map 中使用零值,我们就可以利用这一点 .

    例如,如果值类型是 string ,并且我们知道我们永远不会在 Map 中存储值为空字符串的条目( string 类型的零值),我们还可以通过比较非测试来测试密钥是否在 Map 中 - 索引表达式(的结果)的特殊形式为零值:

    m := map[int]string{
        0: "zero",
        1: "one",
    }
    
    fmt.Printf("Key 0 exists: %t\nKey 1 exists: %t\nKey 2 exists: %t",
        m[0] != "", m[1] != "", m[2] != "")
    

    输出(在Go Playground上试试):

    Key 0 exists: true
    Key 1 exists: true
    Key 2 exists: false
    

    实际上,在很多情况下我们不将零值值存储在 Map 中,因此可以经常使用 . 例如,接口和函数类型的值为零 nil ,我们通常不会将其存储在映射中 . 因此,通过将密钥与 nil 进行比较,可以测试密钥是否在 Map 中 .

    使用此"technique"也有另一个优点:您可以以紧凑的方式检查多个键的存在(您不能使用特殊的"comma ok"表单来执行此操作) . 更多关于此:Check if key exists in multiple maps in one condition

  • 6

    两个值赋值可用于此目的 . 请查看下面的示例程序

    package main
    
    import (
            "fmt"
    )
    
    func main(){
        //creating a map with 3 key-value pairs
        sampleMap := map[string]int {"key1" : 100, "key2" : 500, "key3" : 999}
        //A two value assignment can be used to check existence of a key. 
        value, isKeyPresent := sampleMap["key2"]
        //isKeyPresent will be true if key present in sampleMap        
        if isKeyPresent {
            //key exist
                fmt.Println("key present, value =  ", value)
        } else {
                //key does not exist
                fmt.Println("key does not exist")
        }
    }
    
  • 3

    Edit: 以下答案在Go 1之前 . 从Go 1开始,它不再准确/有效 .


    除了The Go Programming Language Specification之外,你应该阅读Effective Go . 在maps的部分,他们说,除其他外:

    “尝试使用 Map 中不存在的键获取 Map 值将导致程序崩溃,但有一种方法安全地使用多项任务 . “

    var seconds int
    var ok bool
    seconds, ok = timeZone[tz]
    

    “要测试 Map 中的状态而不必担心实际值,可以使用空白标识符,一个简单的下划线(_) . 空白标识符可以使用任何类型的任何值进行分配或声明,并且值无害地丢弃 . 要测试 Map 中的状态,请使用空白标识符代替值的常用变量 . “

    _, present := timeZone[tz]
    
  • 17

    它在"Index expressions"下提到 .

    在特殊形式v的赋值或初始化中使用的类型map [K] V的映射a上的索引表达式,ok = a [x]
    v,ok:= a [x]
    var v,ok = a [x]
    产生一个额外的无类型布尔值 . 如果键x存在于映射中,则ok的值为true,否则为false .

  • 1

    只是用

    if len(m) == 0 {
        ...
    }
    

相关问题