Bir harita üzerinde tekrarlayabileceğimi biliyorum m
,
for k, v := range m { ... }
bir anahtar arayın ancak bir anahtarın bir haritadaki varlığını test etmenin daha etkili bir yolu var mı?
Cevabını dil spesifikasyonunda bulamadım .
Bir harita üzerinde tekrarlayabileceğimi biliyorum m
,
for k, v := range m { ... }
bir anahtar arayın ancak bir anahtarın bir haritadaki varlığını test etmenin daha etkili bir yolu var mı?
Cevabını dil spesifikasyonunda bulamadım .
Yanıtlar:
Bir satır cevap:
if val, ok := dict["foo"]; ok {
//do something here
}
if
Go ifadeleri hem bir koşul hem de bir başlatma ifadesi içerebilir. Yukarıdaki örnek her ikisini de kullanır:
iki değişkeni ilklendirir - val
haritadan "foo" değerini veya "sıfır değeri" (bu durumda boş dize) alır ve haritada "foo" mevcutsa ok
olarak ayarlanacak bir bool alırtrue
değerlendirir ok
, olacak true
"foo" Harita olsaydı
Haritada gerçekten "foo" varsa, if
ifadenin gövdesi yürütülür ve val
bu kapsamda yerel olur.
var val string = ""
aynı kalacaktır, aynı val, ok :=
adda yalnızca o blokta görünür olan yeni bir yerel değişken oluşturur.
if key in dict
.
Go Programlama Dili Spesifikasyonu'na ek olarak , Etkili Go'yu da okumalısınız . Haritalar bölümünde, diğer şeylerin yanı sıra:
Haritada bulunmayan bir anahtarla bir harita değeri getirme girişimi, haritadaki girdilerin türü için sıfır değerini döndürür. Örneğin, harita tamsayılar içeriyorsa, var olmayan bir anahtarın aranması 0 değerini döndürür. Bir küme, değer tipi boole içeren bir harita olarak uygulanabilir. Değeri kümeye koymak için harita girişini true olarak ayarlayın ve ardından basit indeksleme ile test edin.
attended := map[string]bool{ "Ann": true, "Joe": true, ... } if attended[person] { // will be false if person is not in the map fmt.Println(person, "was at the meeting") }
Bazen eksik bir girişi sıfır değerinden ayırmanız gerekir. "UTC" için bir giriş var mı veya haritada olmadığı için bu 0 mı? Birden fazla atama biçimiyle ayrım yapabilirsiniz.
var seconds int var ok bool seconds, ok = timeZone[tz]
Açık nedenlerden dolayı buna “virgül ok” deyimi denir. Bu örnekte, eğer tz mevcutsa, saniyeler uygun şekilde ayarlanacak ve tamam doğru olacaktır; değilse, saniye sıfıra ayarlanır ve tamam yanlış olur. İşte güzel bir hata raporu ile bir araya getiren bir fonksiyon:
func offset(tz string) int { if seconds, ok := timeZone[tz]; ok { return seconds } log.Println("unknown time zone:", tz) return 0 }
Gerçek değer hakkında endişelenmeden haritadaki varlığını test etmek için, değer için normal değişken yerine boş tanımlayıcıyı (_) kullanabilirsiniz.
_, present := timeZone[tz]
Üzerine arandı go-fındık e-posta listesi ve 11/15/2009 tarihinde Peter Froehlich tarafından yayınlanan bir çözüm buldu.
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")
}
}
Veya daha kompakt bir şekilde,
if value, ok := dict["baz"]; ok {
fmt.Println("value: ", value)
} else {
fmt.Println("key not found")
}
İfadenin bu biçimini kullanarak if
, value
ve ok
değişkenlerinin yalnızca if
koşullar içinde görünür olduğunu unutmayın .
_, ok := dict["baz"]; ok
. _
Bölüm geçici bir değişken oluşturmak yerine uzak değerini atar.
_, exists := timeZone[tz] // Just checks for key existence
val, exists := timeZone[tz] // Checks for key existence and retrieves the value
İşte Go Playground'da bir örnek .
Başına Haritalar bölümünde Etkili Go :
Haritada bulunmayan bir anahtarla bir harita değeri getirme girişimi, haritadaki girdilerin türü için sıfır değerini döndürür. Örneğin, harita tamsayılar içeriyorsa, var olmayan bir anahtarı aramak 0 değerini döndürür.
Bazen eksik bir girişi sıfır değerinden ayırmanız gerekir. "UTC" için bir giriş var mı veya boş bir dize var mı, çünkü haritada hiç yok mu? Birden fazla atama biçimiyle ayrım yapabilirsiniz.
var seconds int var ok bool seconds, ok = timeZone[tz]
Açık nedenlerden dolayı buna “virgül ok” deyimi denir. Bu örnekte, eğer tz mevcutsa, saniyeler uygun şekilde ayarlanacak ve tamam doğru olacaktır; değilse, saniye sıfıra ayarlanır ve tamam yanlış olur. İşte güzel bir hata raporu ile bir araya getiren bir fonksiyon:
func offset(tz string) int { if seconds, ok := timeZone[tz]; ok { return seconds } log.Println("unknown time zone:", tz) return 0 }
Gerçek değer hakkında endişelenmeden haritadaki varlığını test etmek için, değer için normal değişken yerine boş tanımlayıcıyı (_) kullanabilirsiniz.
_, present := timeZone[tz]
Diğer cevaplarda belirtildiği gibi, genel çözüm, özel formun bir atamasında bir dizin ifadesi kullanmaktır :
v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]
var v, ok T = a[x]
Bu güzel ve temiz. Bununla birlikte bazı kısıtlamaları vardır: özel bir form ataması olmalıdır. Sağ taraftaki ifade yalnızca harita dizini ifadesi olmalı ve sol taraftaki ifade listesi, önce değer türünün atanabildiği tam olarak 2 işlenen ve değerin atanabileceği ikinci bir işlenen içermelidir bool
. Bu özel formun sonucunun ilk değeri, anahtarla ilişkili değer olacaktır ve ikinci değer, haritada verilen anahtarla gerçekten bir giriş olup olmadığını (anahtar haritada varsa) söyleyecektir. Sol taraftaki ifade listesi , sonuçlardan birine ihtiyaç duyulmadığında da boş tanımlayıcı içerebilir .
Dizinlenmiş harita değeri nil
anahtar içeriyorsa veya anahtar içermiyorsa, dizin ifadesinin haritanın değer türünün sıfır değerini değerlendirdiğini bilmek önemlidir . Yani mesela:
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'da deneyin .
Dolayısıyla, haritamızda sıfır değerini kullanmadığımızı bilirsek, bundan yararlanabiliriz.
Örneğin, değer türü ise string
ve girişleri haritada değerin boş dize ( string
tür için sıfır değeri ) olduğu yerde saklamamış olduğumuzu biliyoruz , özel olmayanları karşılaştırarak anahtarın haritada olup olmadığını da test edebiliriz dizin ifadesinin (sonucunun) sıfır değerine biçimi:
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] != "")
Çıktı ( Go Playground'da deneyin ):
Key 0 exists: true
Key 1 exists: true
Key 2 exists: false
Uygulamada, sıfır değer değerini haritada saklamadığımız birçok durum vardır, bu nedenle bu oldukça sık kullanılabilir. Örneğin, arayüzler ve işlev türlerinin sıfır değeri vardır nil
ve bunlar genellikle haritalarda saklamayız. Böylece bir anahtarın haritada olup olmadığını test etmek, karşılaştırmak suretiyle elde edilebilir nil
.
Bu "tekniği" kullanmanın başka bir avantajı daha vardır: birden çok anahtarın varlığını kompakt bir şekilde kontrol edebilirsiniz (bunu özel "virgül ok" formuyla yapamazsınız). Bununla ilgili daha fazla bilgi: Bir koşulda birden çok haritada anahtar olup olmadığını kontrol edin
Mevcut olmayan bir anahtarla dizin oluştururken değer türünün sıfır değerini elde etmek, bool
değerleri olan haritaları set olarak kullanmamızı da sağlar . Örneğin:
set := map[string]bool{
"one": true,
"two": true,
}
fmt.Println("Contains 'one':", set["one"])
if set["two"] {
fmt.Println("'two' is in the set")
}
if !set["three"] {
fmt.Println("'three' is not in the set")
}
Çıktı verir ( Go Playground'da deneyin ):
Contains 'one': true
'two' is in the set
'three' is not in the set
İlgili bilgilere bakın: Benzersiz dizeler içeren bir diziyi nasıl oluşturabilirim?
T
de var v, ok T = a[x]
? değil ok
bool olmalı?
map[bool]bool
ve T
bir bool
, ancak harita türü ise o da çalışır map[interface{}]bool
ve T
olduğu interface{}
; ayrıca bool
temel türü olan özel türlerle de çalışır , Go Playground'daki hepsini görün . Yani bu form ikame edilmiş birden çok tip için geçerli olduğundan T
, bu yüzden genel T
kullanılır. Türü, türlenmemiş olarak atanabilecek ok
herhangi bir şey olabilir. bool
burada daha iyi bir yol
if _, ok := dict["foo"]; ok {
//do something here
}
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)
Sonra go run maps.go bir şey var mı? doğru yok mu? yanlış
_, ok = m["somestring"]
olmalı=_, ok := m["somestring"]
"Dizin ifadeleri" altında belirtilmiştir .
Özel formun atanmasında veya başlatılmasında kullanılan harita [A] tipi haritadaki bir dizin ifadesi
v, ok = a[x] v, ok := a[x] var v, ok = a[x]
ek bir tiplenmemiş boole değeri verir. Haritada x tuşu varsa ok değeri true, aksi takdirde false olur.
Bu amaçla iki değer ataması kullanılabilir. Lütfen aşağıdaki örnek programımı kontrol edin
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")
}
}