Как проверить, содержит ли карта ключ в go?



Я знаю, что могу перебирать карту m by,



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


и искать ключ, но есть более эффективный способ проверки существования ключа в map? Спасибо. Я не мог найти ответ в язык спецификаций.

776   10  

10 ответов:

одна строка ответа:

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

объяснение:

if операторы в Go могут включать как условие, так и оператор инициализации. В приведенном выше примере используются оба:

  • инициализирует две переменные - val получит либо значение " foo "с карты, либо" нулевое значение " (в данном случае пустая строка) и ok получит bool, который будет установлен в true если "foo" действительно присутствовал в карта

  • оценивает ok, которые будут true если бы "фу" был на карте

если "фу" действительно присутствует на карте, то тело if оператор будет выполнен и val будет локальным для этой области.

Edit: следующий ответ до перехода 1. Начиная с Go 1, он больше не является точным / действительным.


кроме Спецификация Языка Программирования Go следует читать Эффективный Go. В разделе о карты говорят, между прочим:

" попытка получить значение карты с ключом, которого нет на карте, приведет к сбою программы, но есть способ сделать это безопасное использование нескольких назначений."

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

" чтобы проверить наличие на карте, не беспокоясь о фактическом значении, вы можете использовать пустой идентификатор, простое подчеркивание (_). Пустой идентификатор может быть назначен или объявлен с любым значением любого типа, при этом значение отбрасывается безвредно. Для проверки наличия на карте используйте пустой идентификатор вместо обычной переменной для значения."

_, present := timeZone[tz]

поиск go-nuts email list и нашел решение, опубликованное Петром Фролихом 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")
        }
}

или, более компактно,

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

обратите внимание, используя эту форму if заявление value и ok переменные видны только внутри if условиях.

Короткий Ответ:

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

пример

здесь пример на Go Playground.

Более Длинный Ответ

на карты на Эффективный Go:

попытка получить значение карты с ключом, которого нет на карте, вернет нулевое значение для типа записей на карте. Например, если карта содержит целые числа, поиск несуществующего ключ вернет 0.

иногда вам нужно отличить отсутствующую запись от нулевого значения. Есть ли запись для " UTC " или это пустая строка, потому что ее вообще нет на карте? Вы можете различать с помощью формы множественного назначения.

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

по понятным причинам это называется "запятая ОК" фразеологизм. В этом примере, если TZ присутствует, секунды будут установлены соответствующим образом, и ok будет true; если нет, секунды будут установлены на ноль, а ok будет false. Вот функция, которая ставит его вместе с хорошим отчетом об ошибке:

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

чтобы проверить наличие на карте, не беспокоясь о фактическом значении, вы можете использовать пустой идентификатор (_) вместо обычной переменной для значения.

_, present := timeZone[tz]

Как отмечалось в других ответах, общее решение заключается в использовании индексном выражении на задание специальной форме:

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

это красиво и чисто. Однако у него есть некоторые ограничения: это должно быть назначение специальной формы. Правостороннее выражение должно быть только выражением индекса карты, а список левых выражений должен содержать ровно 2 операнда, первый из которых может быть присвоен типу значения, а второй - bool значение присваиваем. Первое значение результата этого специального выражения индекса формы будет значением, связанным с ключом, а второе значение покажет, есть ли на самом деле запись на карте с данным ключом (если ключ существует на карте). Левый список выражений также может содержать пустой идентификатор если один из результатов не требуется.

важно знать, что если индексированное значение карты nil или не содержат ключ, выражение индекса оценивается в нулевое значение типа значения карты. Так например:

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

на Go Playground.

Итак, если мы знаем, что мы не используем нулевое значение в нашей карте, мы можем воспользоваться этим.

например, если тип значения string и мы знаем, что мы никогда не храните записи в карте, где значение является пустой строкой (нулевое значение string тип), мы также можем проверьте, находится ли ключ в карте, сравнивая не специальную форму выражения индекса (результат) с нулевым значением:

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

выход (попробуйте его на Go Playground):

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

на практике есть много случаев, когда мы не храним нулевое значение на карте, поэтому это можно использовать довольно часто. Например, интерфейсы и типы функций имеют нулевое значение nil, который мы часто не храним в картах. Поэтому тестирование, если ключ находится на карте может быть достигнуто путем сравнения его nil.

использование этой " техники "имеет еще одно преимущество: вы можете проверить наличие нескольких ключей компактным способом (вы не можете сделать это с помощью специальной формы" запятая ok"). Подробнее об этом: проверьте, существует ли ключ в нескольких картах в одном условии

лучше здесь

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

он упоминается в разделе "индекс выражений".

индексное выражение на карте a типа map[K]V, используемое в назначении или инициализация специальной формы

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

дает дополнительное нетипизированное логическое значение. Значение ok равно true, если ключ x присутствует на карте, а в противном случае-false.

    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)

затем запустите карты.идти somestring существует? истинный не существует? ложь

для этой цели можно использовать присвоение двух значений. Пожалуйста, проверьте мой пример программы ниже

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

просто использовать

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

Comments

    Ничего не найдено.