web-dev-qa-db-fra.com

Comment vérifier si une carte contient une clé dans Go?

Je sais que je peux parcourir une carte m by,

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

et cherchez une clé, mais existe-t-il un moyen plus efficace de tester l'existence d'une clé dans une carte?

Je n'ai pas trouvé de réponse dans le language spec .

582
grokus

Réponse en ligne:

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

Explication:

Les instructions if dans Go peuvent inclure une condition et une instruction d'initialisation. L'exemple ci-dessus utilise à la fois:

  • initialise deux variables - val recevra soit la valeur "foo" de la carte, soit une "valeur zéro" (dans ce cas, la chaîne vide) et ok recevra un bool qui sera défini sur true si "foo" était réellement présent dans la carte

  • évalue ok, qui sera true si "foo" était dans la carte

Si "foo" est effectivement présent dans la carte, le corps de l'instruction if sera exécuté et val sera local à cette étendue.

1121
marketer

Edit: La réponse suivante est antérieure à Go 1. À partir de Go 1, elle n’est plus exacte/valide.


En plus de Spécification du langage de programmation Go , vous devez lire Effective Go . Dans la section sur cartes , ils disent entre autres:

"Une tentative d'extraction d'une valeur de la carte avec une clé qui n'est pas présente dans la carte provoquera le blocage du programme, mais il existe un moyen de le faire en toute sécurité en utilisant une affectation multiple."

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

"Pour tester la présence sur la carte sans se soucier de la valeur réelle, vous pouvez utiliser l'identifiant vide, un simple trait de soulignement (_). L'identifiant vide peut être attribué ou déclaré avec n'importe quelle valeur, de n'importe quel type, la valeur étant supprimée de manière inoffensive. Pour tester la présence dans une carte, utilisez l'identificateur vide à la place de la variable habituelle pour la valeur. "

_, present := timeZone[tz]
93
peterSO

Vous avez cherché sur = liste de courrier électronique go-nut et trouvé une solution publiée par Peter Froehlich le 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")
        }
}

Ou, plus compactement,

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

Notez que, sous cette forme de l'instruction if, les variables value et ok sont uniquement visibles dans les conditions if.

45
grokus

Réponse courte

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

Exemple

Voici un exemple sur le terrain de je .

Réponse plus longue

Selon la section Maps de Effective Go :

Une tentative d'extraction d'une valeur de carte avec une clé qui n'est pas présente dans la carte renverra la valeur zéro pour le type des entrées dans la carte. Par exemple, si la carte contient des entiers, la recherche d'une clé inexistante renverra 0.

Parfois, vous devez distinguer une entrée manquante d'une valeur nulle. Existe-t-il une entrée pour "UTC" ou s'agit-il d'une chaîne vide car elle ne figure pas du tout dans la carte? Vous pouvez discriminer avec une forme d'affectation multiple.

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

Pour des raisons évidentes, on appelle cela l'idiome "virgule ok". Dans cet exemple, si tz est présent, les secondes seront définies correctement et ok sera vrai; sinon, les secondes seront mises à zéro et ok sera faux. Voici une fonction qui associe un rapport d'erreur de Nice:

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

Pour tester la présence dans la carte sans vous soucier de la valeur réelle, vous pouvez utiliser l'identificateur vide (_) à la place de la variable habituelle pour la valeur.

_, present := timeZone[tz]
20
Matthew Rankin

Comme indiqué par d'autres réponses, la solution générale consiste à utiliser un expression d'index dans un affectation de la forme spéciale:

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

C'est gentil et propre. Il y a cependant quelques restrictions: il doit s'agir d'une cession de forme spéciale. L'expression de droite doit être uniquement l'expression d'index-mappe et la liste des expressions de gauche doit contenir exactement 2 opérandes, le premier auquel le type de valeur est assignable et le second auquel une valeur boolest assignable. La première valeur du résultat de cette expression d'index de formulaire spécial sera la valeur associée à la clé, et la deuxième valeur indiquera s'il existe réellement une entrée dans la carte avec la clé donnée (si la clé existe dans la carte). La liste des expressions de gauche peut également contenir le signe identificateur vide si l'un des résultats n'est pas nécessaire.

Il est important de savoir que si la valeur de la carte indexée est nilou ne contient pas la clé, l'expression d'index est évaluée à valeur zéro du type de valeur de la carte. Donc par exemple:

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

Essayez-le sur le Go Playground .

Donc, si nous savons que nous n'utilisons pas la valeur zéro dans notre carte, nous pouvons en tirer parti.

Par exemple, si le type de valeur est stringet que nous savons que nous ne stockons jamais d'entrées dans la mappe où la valeur est la chaîne vide (valeur zéro pour le type stringname__), nous pouvons également vérifier si la clé est dans la m - forme spéciale de l'expression d'index (résultat de) à la valeur zéro:

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

Sortie (essayez-le sur le Go Playground ):

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

En pratique, il existe de nombreux cas où nous ne stockons pas la valeur zéro dans la carte, ce qui peut être utilisé assez souvent. Par exemple, les interfaces et les types de fonction ont une valeur nulle nilname__, que nous ne stockons souvent pas dans les cartes. Il est donc possible de vérifier si une clé figure sur la carte en la comparant à nilname__.

L'utilisation de cette "technique" présente également un autre avantage: vous pouvez vérifier l'existence de plusieurs clés de manière compacte (vous ne pouvez pas le faire avec le formulaire spécial "comma ok"). Plus à ce sujet: Vérifiez si la clé existe dans plusieurs cartes dans une condition

10
icza

meilleur moyen ici

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

Il est mentionné sous "Index index" .

Une expression d'index sur une carte a de type map [K] V utilisée dans une assignation ou une initialisation de la forme spéciale

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

donne une valeur booléenne supplémentaire non typée. La valeur de ok est true si la clé x est présente dans la carte et false sinon.

4
mroman
    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)

Ensuite, allez exécuter maps.go somestring existe? vrai n'existe pas? faux

3
Lady_Exotel

Une affectation de deux valeurs peut être utilisée à cette fin. S'il vous plaît vérifier mon exemple de programme ci-dessous

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")
    }
}
1
Fathah Rehman P