Как проверить, содержит ли карта ключ в go?
Я знаю, что могу перебирать карту m by,
for k, v := range m { ... }
и искать ключ, но есть более эффективный способ проверки существования ключа в map? Спасибо. Я не мог найти ответ в язык спецификаций.
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.
Более Длинный Ответ
попытка получить значение карты с ключом, которого нет на карте, вернет нулевое значение для типа записей на карте. Например, если карта содержит целые числа, поиск несуществующего ключ вернет 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"). Подробнее об этом: проверьте, существует ли ключ в нескольких картах в одном условии
он упоминается в разделе "индекс выражений".
индексное выражение на карте 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") } }
Comments