英文:
Check if key exists in multiple maps in one condition
问题
我需要检查两个映射中是否存在相同的键:
if v1, ok1 := map1["aaa"]; ok1 {
    ...
}
if v2, ok2 := map2["aaa"]; ok2 {
    ...
}
是否可能将这两个条件合并为一个?我设法做到了这样:
v1, ok1 := map1["aaa"]
v2, ok2 := map2["aaa"]
if ok1 && ok2 {
    ...
}
但我想知道是否可以在一个 if 条件中完成赋值和检查。
英文:
I need to check if the same key exists in two maps:
if v1, ok1 := map1["aaa"]; ok1 {
 ...
}
if v2, ok2 := map2["aaa"]; ok2 {
 ...
}
Is it possible to join these two conditions into one? I managed to do something like this:
v1, ok1 := map1["aaa"]
v2, ok2 := map2["aaa"]
if ok1 && ok2 {
 ...
}
but I'm curious whether it (assigning and checking) can be done in one if condition.
答案1
得分: 8
不,这是不可能的。规范:索引表达式:
在特殊形式的赋值或初始化中,对类型为map[K]V的映射a进行索引表达式操作,例如:
v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]
会产生一个额外的无类型布尔值。如果键x存在于映射中,ok的值为true,否则为false。
因此,只有在没有其他赋值操作时,才能使用特殊的v, ok := m[k]形式。
然而,如果你不使用映射值类型的零值,你可以使用简单的元组赋值来进行检查;通过不使用特殊形式,而是使用两个简单的索引表达式。
例如,如果你的值类型是某个接口类型(例如interface{}),并且你知道你不使用nil值,你可以这样做:
if v1, v2 := m1["aaa"], m2["aaa"]; v1 != nil && v2 != nil {
    fmt.Printf("Both map contains key 'aaa': %v, %v\n", v1, v2)
}
当然,通过一个辅助函数,你可以一步完成:
func idx(m1, m2 map[string]interface{}, k string) (
    v1, v2 interface{}, ok1, ok2 bool) {
    v1, ok1 = m1[k]
    v2, ok2 = m2[k]
    return
}
使用它:
if v1, v2, ok1, ok2 := idx(m1, m2, "aaa"); ok1 && ok2 {
    fmt.Printf("Both map contains key 'aaa': %v, %v\n", v1, v2)
}
在Go Playground上尝试这些示例。
英文:
No, it can't be done. Spec: Index expressions:
> An index expression on a map a of type map[K]V used in an assignment or initialization of the special form
>
>     v, ok = a[x]
>     v, ok := a[x]
>     var v, ok = a[x]
>
> yields an additional untyped boolean value. The value of ok is true if the key x is present in the map, and false otherwise.
So you can use the special v, ok := m[k] form only if nothing else gets assigned.
However, if you don't use the zero value of the value type of the map, you can do the check using a simple tuple-assignment; by not using the special form but 2 simple index expressions.
For example if your value type is some interface type (e.g. interface{}), and you know you don't use the nil value, you may do the following:
if v1, v2 := m1["aaa"], m2["aaa"]; v1 != nil && v2 != nil {
    fmt.Printf("Both map contains key '%s': %v, %v\n", "aaa", v1, v2)
}
Of course with a helper function, you can do it in one step:
func idx(m1, m2 map[string]interface{}, k string) (
    v1, v2 interface{}, ok1, ok2 bool) {
    v1, ok1 = m1[k]
    v2, ok2 = m2[k]
    return
}
Using it:
if v1, v2, ok1, ok2 := idx(m1, m2, "aaa"); ok1 && ok2 {
    fmt.Printf("Both map contains key '%s': %v, %v\n", "aaa", v1, v2)
}
Try the examples on the Go Playground.
答案2
得分: 0
你也可以使用可变参数(三个点)来检查多个键:
// 检查 map1 和 map2 是否为空
func checkMap(m1, m2 map[string]interface{}, keys ...string) []bool {
    var isExist []bool
    for _, key := range keys {
        // 从 map1 检查值
        _, ok := m1[key]
        if ok {
            isExist = append(isExist, true) // 第一次追加以避免 panic
        } else {
            isExist = append(isExist, false) // 第一次追加以避免 panic
        }
        // 从 map2 检查值
        _, ok = m2[key]
        if ok {
            isExist[len(isExist)-1] = true
        } else {
            isExist[len(isExist)-1] = false
        }
    }
    return isExist
}
然后你可以按顺序检查你的键,像这样:
result := checkMap(myMap, myMap2, "a", "b", "c", "d", "e", "f", "g")
fmt.Printf("result = %+v\n", result) // 打印结果
if result[0] {
    fmt.Println("key a 在两个 map 中存在")
}
if result[1] {
    fmt.Println("key b 在两个 map 中存在")
}
英文:
you could also use variadic parameter(three dots) to check multiple keys :
// check map 1 and map2 is null or not
func checkMap(m1, m2 map[string]interface{}, keys ...string) []bool {
	var isExist []bool
	for key := range keys {
		//checking value from map 1
		_, ok := m1[keys[key]]
		if ok {
			isExist = append(isExist, true) // append for the first time to avoid panic
		} else {
			isExist = append(isExist, false) // append for the first time to avoid panic
		}
		// checking value from map2
		_, ok = m2[keys[key]]
		if ok {
			isExist[key] = true
		} else {
			isExist[key] = false
		}
	}
	return isExist
}
And then you can check your keys in order like this :
result := checkMap(myMap, myMap2, "a", "b", "c", "d", "e", "f", "g")
fmt.Printf("result = %+v\n", result) // print the result
if result[0] {
	fmt.Println("key a exist in both map")
}
if result[1] {
	fmt.Println("key b exist in both map")
} 
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论