dictionary go - ¿Cómo comprobar si un mapa contiene una clave en ir?





definition english (10)


Solo usa

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

Sé que puedo recorrer un mapa m,

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

y busque una clave, pero ¿existe una manera más eficiente de probar la existencia de una clave en un mapa? Gracias. No pude encontrar una respuesta en la especificación de idioma .




Una línea de respuesta:

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

Explicación:

if declaraciones en Go pueden incluir una condición y una instrucción de inicialización. El ejemplo anterior utiliza ambos:

  • inicializa dos variables: val recibirá el valor de "foo" del mapa o un "valor cero" (en este caso, la cadena vacía) y ok recibirá un valor bool que se establecerá en true si "foo" estaba realmente presente en el mapa

  • evalúa ok , lo que será true si "foo" estaba en el mapa

Si "foo" está presente en el mapa, el cuerpo de la sentencia if se ejecutará y val será local para ese alcance.




mejor camino aquí

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



    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)

Entonces, ve a correr maps.go existe alguna cosa? verdad no existe? falso




Respuesta corta

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

Ejemplo

Aquí hay un ejemplo en el Go Playground .

Respuesta más larga

Por la sección de Maps de Maps :

Un intento de obtener un valor de mapa con una clave que no está presente en el mapa devolverá el valor cero para el tipo de las entradas en el mapa. Por ejemplo, si el mapa contiene enteros, buscar una clave no existente devolverá 0.

A veces es necesario distinguir una entrada que falta de un valor cero. ¿Hay una entrada para "UTC" o es la cadena vacía porque no está en el mapa en absoluto? Puedes discriminar con una forma de asignación múltiple.

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

Por razones obvias, esto se llama el idioma "coma bien". En este ejemplo, si tz está presente, los segundos se establecerán adecuadamente y ok será cierto; Si no, los segundos se establecerán en cero y ok será falso. Aquí hay una función que lo pone junto con un buen informe de errores:

func offset(tz string) int {
    if seconds, ok := timeZone[tz]; ok {
        return seconds
    }
    log.Println("unknown time zone:", tz)
    return 0
}

Para probar la presencia en el mapa sin preocuparse por el valor real, puede usar el identificador en blanco (_) en lugar de la variable habitual para el valor.

_, present := timeZone[tz]



Se puede usar una asignación de dos valores para este propósito. Por favor, consulte mi programa de muestra a continuación

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



Edición: la siguiente respuesta es anterior a Go 1. Comenzando con Go 1, ya no es precisa / válida.

Además de la especificación del lenguaje de programación The Go , debe leer Effective Go . En la sección de maps , dicen, entre otras cosas:

"Un intento de obtener un valor de mapa con una clave que no está presente en el mapa hará que el programa se bloquee, pero hay una manera de hacerlo de manera segura utilizando una asignación múltiple".

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

"Para probar la presencia en el mapa sin preocuparse por el valor real, puede usar el identificador en blanco, un subrayado simple (_). El identificador en blanco se puede asignar o declarar con cualquier valor de cualquier tipo, con el valor descartado sin causar daños. Para probar la presencia en un mapa, use el identificador en blanco en lugar de la variable habitual para el valor ".

_, present := timeZone[tz]



Se menciona en "Expresiones de índice" .

Una expresión de índice en un mapa de tipo map [K] V utilizado en una asignación o inicialización de la forma especial

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

produce un valor booleano sin tipo adicional. El valor de ok es verdadero si la clave x está presente en el mapa y, de lo contrario, es falso.




Como lo señalan otras respuestas, la solución general es usar una expresión de índice en una assignment de la forma especial:

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

Esto es agradable y limpio. Sin embargo, tiene algunas restricciones: debe ser una asignación de forma especial. La expresión del lado derecho debe ser solo la expresión del índice del mapa, y la lista de expresiones de la izquierda debe contener exactamente 2 operandos, primero a los que se puede asignar el tipo de valor y un segundo al que se puede bool un valor bool . El primer valor del resultado de esta expresión de índice de formulario especial será el valor asociado con la clave, y el segundo valor dirá si realmente hay una entrada en el mapa con la clave dada (si la clave existe en el mapa). La lista de expresiones del lado izquierdo también puede contener el identificador en blanco si no se necesita uno de los resultados.

Es importante saber que si el valor del mapa indexado es nil o no contiene la clave, la expresión de índice se evalúa al valor cero del tipo de valor del mapa. Así por ejemplo:

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

Pruébalo en el Go Playground .

Entonces, si sabemos que no usamos el valor cero en nuestro mapa, podemos aprovechar esto.

Por ejemplo, si el tipo de valor es string , y sabemos que nunca almacenamos entradas en el mapa donde el valor es la cadena vacía (valor cero para el tipo de string ), también podemos probar si la clave está en el mapa comparando la no - Forma especial de la expresión de índice (resultado de) en el valor cero:

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] != "")

Salida (pruébalo en el Go Playground ):

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

En la práctica, hay muchos casos en los que no almacenamos el valor de valor cero en el mapa, por lo que se puede usar con bastante frecuencia. Por ejemplo, las interfaces y los tipos de funciones tienen un valor nil , que a menudo no almacenamos en los mapas. Por lo tanto, se puede comprobar si una clave está en el mapa comparándola con nil .

El uso de esta "técnica" también tiene otra ventaja: puede verificar la existencia de múltiples claves de forma compacta (no puede hacerlo con el formulario especial "coma bien"). Más sobre esto: verifique si la clave existe en varios mapas en una condición




Utilice dict.pop() :

my_dict.pop('key', None)

Esto devolverá my_dict[key] si la key existe en el diccionario, y None caso contrario. Si no se especifica el segundo parámetro (es decir, my_dict.pop('key') ) y la key no existe, se KeyError un KeyError .







dictionary go