11

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.

2 Answers 2

8

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Being relatively new to golang I have to say that if v1, v2, ok1, ok2 := idx(m1, m2, "aaa"); ok1 && ok2 { looks like a contributing risk factor for intraocular melanoma. A.k.a. eye cancer.
@jangroth I wouldn't use it either, but that's a possibility to do what the asker wanted.
0

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")
} 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.