Jak sprawdzić, czy mapa zawiera klucz w go?

I know I can iterate over a map m by,

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

I szukać klucza, ale czy istnieje bardziej efektywny sposób testowania istnienia klucza na mapie? Dzięki. Nie mogłem znaleźć odpowiedzi w Spec języka.

 464
Author: Pablo Jomer, 2010-01-12

10 answers

Odpowiedź w jednej linii:

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

Wyjaśnienie:

if instrukcje w Go mogą zawierać zarówno warunek, jak i instrukcję inicjalizacji. W powyższym przykładzie używa się zarówno:

  • Inicjalizuje dwie zmienne - val otrzyma wartość " foo "z mapy lub" wartość zerową "(w tym przypadku pusty łańcuch) i ok otrzyma bool, który zostanie ustawiony na true Jeśli " foo " faktycznie było obecne na mapie

  • Ocenia ok, która będzie true Jeśli " foo " było na mapie

Jeśli "foo" jest rzeczywiście obecne na mapie, ciało instrukcji if zostanie wykonane i val będzie lokalne dla tego zakresu.

 881
Author: marketer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-20 07:18:01

Edit: następująca odpowiedź jest przed Go 1. Począwszy od Go 1, nie jest już dokładny / ważny.


Oprócz specyfikacji języka programowania Go , powinieneś przeczytać Effective Go . W sekcji O mapach mówią między innymi:

" próba pobrania wartości mapy za pomocą klucza, który nie jest obecny na mapie, spowoduje awarię programu, ale istnieje sposób, aby to zrobić bezpiecznie za pomocą wielokrotnego zadanie."

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

" aby sprawdzić obecność na mapie bez martwienia się o rzeczywistą wartość, możesz użyć pustego identyfikatora, prostego podkreślenia (_). Pusty identyfikator może być przypisany lub zadeklarowany dowolną wartością dowolnego typu, z wartością odrzuconą bez szkody. Aby sprawdzić obecność na mapie, Użyj pustego identyfikatora zamiast zwykłej zmiennej dla wartości."

_, present := timeZone[tz]
 89
Author: peterSO,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-06 07:06:12

Przeszukałem go-nuts e-mail list i znalazłem rozwiązanie opublikowane przez Peter Froehlich w dniu 11/15/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")
        }
}

Lub, bardziej zwięźle,

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

Uwaga, używając tej formy instrukcji if, zmienne value i ok są widoczne tylko wewnątrz warunków if.

 38
Author: grokus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-12 19:01:37

Krótka Odpowiedź

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

Przykład

Oto przykład na Placu Zabaw Go .

Dłuższa Odpowiedź

Na Maps sekcja Effective Go :

Próba pobrania wartości mapy za pomocą klucza, którego nie ma na mapie, zwróci wartość zerową dla typu wpisów na mapie. Na przykład, jeśli mapa zawiera liczby całkowite, wyszukanie nieistniejącego klucza zwróci 0.

Czasami trzeba odróżnić brakujący wpis od wartości zerowej. Czy jest wpis dla " UTC " czy jest to pusty ciąg, ponieważ nie ma go na mapie w ogóle? Można rozróżnić za pomocą formy wielokrotnego przypisania.

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

Z oczywistych powodów nazywa się to idiomem "przecinek ok". W tym przykładzie, jeśli występuje TZ, seconds będzie ustawione odpowiednio i ok będzie true; jeśli nie, seconds będzie ustawione na zero, a ok będzie false. Oto funkcja, która łączy go z ładnym błędem raport:

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

Aby sprawdzić obecność na mapie bez martwienia się o rzeczywistą wartość, możesz użyć pustego identyfikatora ( _ ) zamiast zwykłej zmiennej dla wartości.

_, present := timeZone[tz]
 15
Author: Matthew Rankin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-09 21:38:00

Jak zauważają inne odpowiedzi, ogólnym rozwiązaniem jest użycie wyrażenia indeksowego w przydziale postaci specjalnej:

v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]
var v, ok T = a[x]
To jest ładne i czyste. Ma jednak pewne ograniczenia: musi to być przypisanie specjalnej formy. Wyrażenie po prawej stronie musi być tylko wyrażeniem indeksu mapy, a lista wyrażeń po lewej stronie musi zawierać dokładnie 2 operandy, pierwszy do których można przypisać typ wartości, a drugi do którego można przypisać wartość bool. Pierwszą wartością wyniku wyrażenia indeksu postaci specjalnej będzie wartość powiązana z kluczem, a druga wartość powie, czy rzeczywiście istnieje wpis na mapie z danym kluczem(jeśli klucz istnieje na mapie). Lista wyrażeń po lewej stronie może również zawierać pusty identyfikator , jeśli jeden z wyników nie jest potrzebny.

Ważne jest, aby wiedzieć, że jeśli zindeksowana wartość mapy to nil lub nie zawiera klucza, wyrażenie indeksuje do wartość zerowa typu value mapy. Tak na przykład:

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

Spróbuj na Go Playground.

Więc jeśli wiemy, że nie używamy wartości zerowej na naszej mapie, możemy to wykorzystać.

Na przykład, jeśli typem wartości jest string, A wiemy, że nigdy nie przechowujemy wpisów na mapie, gdzie wartość jest pustym łańcuchem (wartość zerowa dla typu string), możemy również sprawdzić, czy klucz znajduje się na mapie, porównując nie-specjalną formę (wynik wyrażenie indeksu) do wartości zerowej:

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

Output (try it on the Go Playground):

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

W praktyce jest wiele przypadków, gdy nie przechowujemy wartości zerowej na mapie, więc może to być używane dość często. Na przykład interfejsy i typy funkcji mają wartość zerową nil, której często nie przechowujemy w Mapach. Tak więc sprawdzenie, czy klucz znajduje się na mapie, można uzyskać porównując go z nil.

Używanie tej "techniki" ma też inną zaletę: ty można sprawdzić istnienie wielu klawiszy w sposób zwarty (nie można tego zrobić za pomocą specjalnego formularza "przecinek ok"). Więcej na ten temat: sprawdź, czy klucz istnieje na wielu mapach w jednym warunkiem

 6
Author: icza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:50

Better way here

if _, ok := dict["foo"]; ok {
    //do something here
}
 4
Author: Amazingandyyy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-18 05:17:21

Jest wymieniony w "wyrażenia indeksowe" .

Wyrażenie indeksowe na mapie a typu map [K]V użyte w przypisaniu lub inicjalizacja specjalnego formularza

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

Daje dodatkową nietypowaną wartość logiczną. Wartość ok Jest Prawdziwa, jeśli klucz x jest obecny na mapie, a w przeciwnym razie fałszywy.

 3
Author: mroman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-13 18:54:48
    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)
/ Align = "left" / idź. coś istnieje? prawda nie istnieje? false
 2
Author: Lady_Exotel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-22 12:19:35

Do tego celu można użyć przypisania dwóch wartości. Proszę sprawdzić mój przykładowy program poniżej

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")
    }
}
 0
Author: Fathah Rehman P,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-21 10:27:31

Po prostu użyj

if len(m) == 0 {
    ...
}
 -13
Author: hacky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-02 05:10:15