Saya tahu saya bisa mengulangi peta m
dengan,
for k, v := range m { ... }
dan mencari kunci tetapi apakah ada cara yang lebih efisien untuk menguji keberadaan kunci di peta?
Saya tidak dapat menemukan jawabannya dalam spesifikasi bahasa .
Saya tahu saya bisa mengulangi peta m
dengan,
for k, v := range m { ... }
dan mencari kunci tetapi apakah ada cara yang lebih efisien untuk menguji keberadaan kunci di peta?
Saya tidak dapat menemukan jawabannya dalam spesifikasi bahasa .
Jawaban:
Satu jawaban baris:
if val, ok := dict["foo"]; ok {
//do something here
}
if
pernyataan dalam Go dapat mencakup kondisi dan pernyataan inisialisasi. Contoh di atas menggunakan keduanya:
menginisialisasi dua variabel - val
akan menerima nilai "foo" dari peta atau "nilai nol" (dalam hal ini string kosong) dan ok
akan menerima bool yang akan ditetapkan true
jika "foo" benar-benar ada di peta
mengevaluasi ok
, yang akan terjadi true
jika "foo" ada di peta
Jika "foo" memang ada di peta, badan if
pernyataan akan dieksekusi dan val
akan menjadi lokal untuk ruang lingkup itu.
var val string = ""
akan tetap sama, val, ok :=
membuat variabel lokal baru dengan nama yang sama yang hanya dapat dilihat di blok itu.
if key in dict
.
Selain Spesifikasi Bahasa Pemrograman Go , Anda harus membaca Efektif Go . Di bagian peta , kata mereka, antara lain:
Upaya mengambil nilai peta dengan kunci yang tidak ada di peta akan mengembalikan nilai nol untuk jenis entri di peta. Misalnya, jika peta berisi bilangan bulat, mencari kunci yang tidak ada akan mengembalikan 0. Satu set dapat diimplementasikan sebagai peta dengan tipe bool nilai. Setel entri peta menjadi true untuk meletakkan nilai dalam set, dan kemudian mengujinya dengan pengindeksan sederhana.
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") }
Terkadang Anda perlu membedakan entri yang hilang dari nilai nol. Apakah ada entri untuk "UTC" atau 0 karena itu sama sekali tidak ada di peta? Anda dapat membeda-bedakan dengan bentuk penugasan ganda.
var seconds int var ok bool seconds, ok = timeZone[tz]
Untuk alasan yang jelas ini disebut idiom "koma ok". Dalam contoh ini, jika tz ada, detik akan diset dengan tepat dan ok akan benar; jika tidak, detik akan diatur ke nol dan ok akan salah. Berikut adalah fungsi yang menggabungkannya dengan laporan kesalahan yang bagus:
func offset(tz string) int { if seconds, ok := timeZone[tz]; ok { return seconds } log.Println("unknown time zone:", tz) return 0 }
Untuk menguji keberadaan di peta tanpa khawatir tentang nilai aktual, Anda dapat menggunakan pengidentifikasi kosong (_) sebagai pengganti variabel biasa untuk nilai tersebut.
_, present := timeZone[tz]
Mencari di daftar email go-nuts dan menemukan solusi yang diposting oleh Peter Froehlich pada 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")
}
}
Atau, lebih kompak,
if value, ok := dict["baz"]; ok {
fmt.Println("value: ", value)
} else {
fmt.Println("key not found")
}
Catatan, menggunakan bentuk if
pernyataan ini, variabel value
dan ok
hanya terlihat di dalam if
kondisi.
_, ok := dict["baz"]; ok
. Bagian _
membuang nilai alih-alih membuat variabel sementara.
_, exists := timeZone[tz] // Just checks for key existence
val, exists := timeZone[tz] // Checks for key existence and retrieves the value
Berikut ini contoh di Go Playground .
Per bagian Peta dari Go Efektif :
Upaya mengambil nilai peta dengan kunci yang tidak ada di peta akan mengembalikan nilai nol untuk jenis entri di peta. Misalnya, jika peta berisi bilangan bulat, mencari kunci yang tidak ada akan mengembalikan 0.
Terkadang Anda perlu membedakan entri yang hilang dari nilai nol. Apakah ada entri untuk "UTC" atau apakah itu string kosong karena tidak ada di peta sama sekali? Anda dapat membeda-bedakan dengan bentuk penugasan ganda.
var seconds int var ok bool seconds, ok = timeZone[tz]
Untuk alasan yang jelas ini disebut idiom "koma ok". Dalam contoh ini, jika tz ada, detik akan diset dengan tepat dan ok akan benar; jika tidak, detik akan diatur ke nol dan ok akan salah. Berikut adalah fungsi yang menggabungkannya dengan laporan kesalahan yang bagus:
func offset(tz string) int { if seconds, ok := timeZone[tz]; ok { return seconds } log.Println("unknown time zone:", tz) return 0 }
Untuk menguji keberadaan di peta tanpa khawatir tentang nilai aktual, Anda dapat menggunakan pengidentifikasi kosong (_) sebagai pengganti variabel biasa untuk nilai tersebut.
_, present := timeZone[tz]
Seperti dicatat oleh jawaban lain, solusi umum adalah dengan menggunakan ekspresi indeks dalam penugasan bentuk khusus:
v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]
var v, ok T = a[x]
Ini bagus dan bersih. Meskipun memiliki beberapa batasan: itu harus berupa penugasan bentuk khusus. Ekspresi sisi kanan harus hanya ekspresi indeks peta, dan daftar ekspresi tangan kiri harus berisi tepat 2 operan, pertama yang jenis nilai dapat ditugaskan, dan yang kedua dimana bool
nilai ditugaskan. Nilai pertama dari hasil bentuk khusus ini akan menjadi nilai yang terkait dengan kunci, dan nilai kedua akan memberi tahu apakah sebenarnya ada entri di peta dengan kunci yang diberikan (jika kunci ada di peta). Daftar ekspresi sisi kiri juga dapat berisi pengidentifikasi kosong jika salah satu hasil tidak diperlukan.
Penting untuk diketahui bahwa jika nilai peta yang diindeks adalah nil
atau tidak mengandung kunci, ekspresi indeks dievaluasi ke nilai nol dari jenis nilai peta. Jadi misalnya:
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
Cobalah di Go Playground .
Jadi jika kita tahu bahwa kita tidak menggunakan nilai nol di peta kita, kita bisa mengambil keuntungan dari ini.
Sebagai contoh jika jenis nilai adalah string
, dan kita tahu kita tidak pernah menyimpan entri di peta di mana nilainya adalah string kosong (nilai nol untuk string
jenis), kita juga dapat menguji apakah kuncinya ada di peta dengan membandingkan non-khusus bentuk (hasil dari) ekspresi indeks ke nilai nol:
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 (coba di Go Playground ):
Key 0 exists: true
Key 1 exists: true
Key 2 exists: false
Dalam praktiknya ada banyak kasus di mana kami tidak menyimpan nilai nol di peta, jadi ini bisa digunakan cukup sering. Misalnya antarmuka dan tipe fungsi memiliki nilai nol nil
, yang sering tidak kami simpan di peta. Jadi menguji apakah kunci di peta dapat dicapai dengan membandingkannya nil
.
Menggunakan "teknik" ini memiliki keuntungan lain juga: Anda dapat memeriksa keberadaan beberapa tombol dengan cara yang ringkas (Anda tidak dapat melakukannya dengan bentuk "koma ok" khusus). Lebih lanjut tentang ini: Periksa apakah ada kunci di beberapa peta dalam satu kondisi
Mendapatkan nilai nol dari tipe nilai saat pengindeksan dengan kunci yang tidak ada juga memungkinkan kita untuk menggunakan peta dengan bool
nilai - nilai sesuai set . Sebagai contoh:
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")
}
Ini menghasilkan (coba di Go Playground ):
Contains 'one': true
'two' is in the set
'three' is not in the set
Lihat yang terkait: Bagaimana saya bisa membuat array yang berisi string unik?
T
di dalam var v, ok T = a[x]
? bukankah ok
harus bool?
map[bool]bool
dan T
adalah bool
, tetapi juga bekerja jika peta adalah tipe map[interface{}]bool
dan T
adalah interface{}
; selain itu juga berfungsi dengan tipe khusus bool
sebagai tipe yang mendasari, lihat semua di Go Playground . Jadi karena formulir itu valid dengan beberapa jenis yang diganti T
, itu sebabnya yang umum T
digunakan. Jenis ok
dapat berupa apa saja yang dapat diberikan pada siapa yang tidak diberi tagbool
.
cara yang lebih baik di sini
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)
Lalu, jalankan menjalankan maps.go suatu tempat ada? benarkah tidak ada? Salah
_, ok = m["somestring"]
seharusnya =_, ok := m["somestring"]
Disebutkan di bawah "Ekspresi indeks" .
Ekspresi indeks pada peta tipe peta [K] V yang digunakan dalam penugasan atau inisialisasi bentuk khusus
v, ok = a[x] v, ok := a[x] var v, ok = a[x]
menghasilkan nilai boolean untyped tambahan. Nilai ok benar jika kunci x ada di peta, dan salah jika tidak.
Penugasan dua nilai dapat digunakan untuk tujuan ini. Silakan periksa program sampel saya di bawah ini
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")
}
}