dictionary - meaning - ¿Cómo comprobar si un mapa contiene una clave en ir?
take definition (10)
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 .
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]
Busqué en la lista de correos electrónicos de idiotas y encontré una solución publicada por Peter Froehlich el 15/11/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")
}
}
O, más compacto,
if value, ok := dict["baz"]; ok {
fmt.Println("value: ", value)
} else {
fmt.Println("key not found")
}
Tenga en cuenta que, utilizando esta forma de la declaración if
, el value
y las variables ok
solo son visibles dentro de las condiciones if
.
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
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.
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")
}
}
Solo usa
if len(m) == 0 {
...
}
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) yok
recibirá un valor bool que se establecerá entrue
si "foo" estaba realmente presente en el mapaevalú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
}
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]
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