Tôi biết tôi có thể lặp lại trên bản đồ mbằng cách,
for k, v := range m { ... }
và tìm kiếm một khóa nhưng có cách nào hiệu quả hơn để kiểm tra sự tồn tại của khóa trong bản đồ không?
Tôi không thể tìm thấy câu trả lời trong thông số ngôn ngữ .
Tôi biết tôi có thể lặp lại trên bản đồ mbằng cách,
for k, v := range m { ... }
và tìm kiếm một khóa nhưng có cách nào hiệu quả hơn để kiểm tra sự tồn tại của khóa trong bản đồ không?
Tôi không thể tìm thấy câu trả lời trong thông số ngôn ngữ .
Câu trả lời:
Một dòng trả lời:
if val, ok := dict["foo"]; ok {
//do something here
}
ifcác câu lệnh trong Go có thể bao gồm cả một điều kiện và một câu lệnh khởi tạo. Ví dụ trên sử dụng cả hai:
khởi tạo hai biến - valsẽ nhận giá trị "foo" từ bản đồ hoặc "giá trị 0" (trong trường hợp này là chuỗi rỗng) và oksẽ nhận được một bool sẽ được đặt thành truenếu "foo" thực sự có trong bản đồ
đánh giá ok, sẽ là truenếu "foo" có trong bản đồ
Nếu "foo" thực sự có mặt trên bản đồ, phần thân của ifcâu lệnh sẽ được thực thi và valsẽ cục bộ trong phạm vi đó.
var val string = ""sẽ giữ nguyên, val, ok :=tạo ra một biến cục bộ mới có cùng tên chỉ có thể nhìn thấy trong khối đó.
if key in dict.
Ngoài Đặc tả ngôn ngữ lập trình Go , bạn nên đọc Go hiệu quả . Trong phần trên bản đồ , họ nói, trong số những thứ khác:
Cố gắng tìm nạp một giá trị bản đồ bằng một khóa không có trong bản đồ sẽ trả về giá trị 0 cho loại mục nhập trong bản đồ. Chẳng hạn, nếu bản đồ chứa các số nguyên, tra cứu khóa không tồn tại sẽ trả về 0. Một tập hợp có thể được thực hiện dưới dạng bản đồ với bool loại giá trị. Đặt mục nhập bản đồ thành true để đặt giá trị trong tập hợp, sau đó kiểm tra nó bằng cách lập chỉ mục đơn giản.
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") }Đôi khi bạn cần phân biệt một mục bị thiếu với giá trị bằng không. Có một mục cho "UTC" hay là 0 vì nó hoàn toàn không có trong bản đồ? Bạn có thể phân biệt với một hình thức nhiều bài tập.
var seconds int var ok bool seconds, ok = timeZone[tz]Vì những lý do rõ ràng, nó được gọi là thành ngữ và dấu phẩy ok. Trong ví dụ này, nếu tz có mặt, giây sẽ được đặt một cách thích hợp và ok sẽ là đúng; nếu không, giây sẽ được đặt thành 0 và ok sẽ sai. Đây là một chức năng kết hợp nó với một báo cáo lỗi hay:
func offset(tz string) int { if seconds, ok := timeZone[tz]; ok { return seconds } log.Println("unknown time zone:", tz) return 0 }Để kiểm tra sự hiện diện trong bản đồ mà không phải lo lắng về giá trị thực tế, bạn có thể sử dụng mã định danh trống (_) thay cho biến thông thường cho giá trị.
_, present := timeZone[tz]
Tìm kiếm trên danh sách email go-nut và tìm thấy một giải pháp được đăng bởi Peter Froehlich vào ngày 15/11/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")
}
}
Hoặc, gọn hơn,
if value, ok := dict["baz"]; ok {
fmt.Println("value: ", value)
} else {
fmt.Println("key not found")
}
Lưu ý, sử dụng hình thức này của ifcâu lệnh, các biến valuevà okchỉ được hiển thị bên trong các ifđiều kiện.
_, ok := dict["baz"]; ok. Phần _ném giá trị đi thay vì tạo một biến tạm thời.
_, exists := timeZone[tz] // Just checks for key existence
val, exists := timeZone[tz] // Checks for key existence and retrieves the value
Đây là một ví dụ tại Sân chơi Go .
Theo phần Bản đồ của Đi hiệu quả :
Cố gắng tìm nạp một giá trị bản đồ bằng một khóa không có trong bản đồ sẽ trả về giá trị 0 cho loại mục nhập trong bản đồ. Chẳng hạn, nếu bản đồ chứa các số nguyên, tra cứu khóa không tồn tại sẽ trả về 0.
Đôi khi bạn cần phân biệt một mục bị thiếu với giá trị bằng không. Có một mục cho "UTC" hay đó là chuỗi trống vì nó hoàn toàn không có trong bản đồ? Bạn có thể phân biệt với một hình thức nhiều bài tập.
var seconds int var ok bool seconds, ok = timeZone[tz]Vì những lý do rõ ràng, nó được gọi là thành ngữ và dấu phẩy ok. Trong ví dụ này, nếu tz có mặt, giây sẽ được đặt một cách thích hợp và ok sẽ là đúng; nếu không, giây sẽ được đặt thành 0 và ok sẽ sai. Đây là một chức năng kết hợp nó với một báo cáo lỗi hay:
func offset(tz string) int { if seconds, ok := timeZone[tz]; ok { return seconds } log.Println("unknown time zone:", tz) return 0 }Để kiểm tra sự hiện diện trong bản đồ mà không phải lo lắng về giá trị thực tế, bạn có thể sử dụng mã định danh trống (_) thay cho biến thông thường cho giá trị.
_, present := timeZone[tz]
Như đã lưu ý bởi các câu trả lời khác, giải pháp chung là sử dụng biểu thức chỉ mục trong một phép gán của dạng đặc biệt:
v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]
var v, ok T = a[x]
Điều này là tốt đẹp và sạch sẽ. Nó có một số hạn chế mặc dù: nó phải là một sự phân công của hình thức đặc biệt. Biểu thức phía bên phải chỉ là biểu thức chỉ mục bản đồ và danh sách biểu thức bên trái phải chứa chính xác 2 toán hạng, đầu tiên là loại giá trị được gán và một boolgiá trị có thể gán được. Giá trị đầu tiên của kết quả của hình thức đặc biệt này sẽ là giá trị được liên kết với khóa và giá trị thứ hai sẽ cho biết nếu thực sự có một mục trong bản đồ với khóa đã cho (nếu khóa tồn tại trong bản đồ). Danh sách biểu thức phía bên trái cũng có thể chứa định danh trống nếu không cần một trong các kết quả.
Điều quan trọng cần biết là nếu giá trị bản đồ được lập chỉ mục có nilhoặc không chứa khóa, biểu thức chỉ mục sẽ ước tính giá trị 0 của loại giá trị của bản đồ. Ví dụ:
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
Hãy thử nó trên Sân chơi Go .
Vì vậy, nếu chúng tôi biết rằng chúng tôi không sử dụng giá trị 0 trong bản đồ của mình, chúng tôi có thể tận dụng lợi thế này.
Ví dụ: nếu loại giá trị là stringvà chúng tôi biết rằng chúng tôi không bao giờ lưu trữ các mục trong bản đồ trong đó giá trị là chuỗi trống (giá trị 0 cho stringloại), chúng tôi cũng có thể kiểm tra xem khóa có trong bản đồ hay không bằng cách so sánh không đặc biệt dạng của biểu thức chỉ số (kết quả của) đến giá trị 0:
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] != "")
Đầu ra (thử trên Sân chơi Go ):
Key 0 exists: true
Key 1 exists: true
Key 2 exists: false
Trong thực tế, có nhiều trường hợp chúng ta không lưu trữ giá trị 0 trong bản đồ, vì vậy điều này có thể được sử dụng khá thường xuyên. Ví dụ: giao diện và loại chức năng có giá trị bằng 0 nil, mà chúng ta thường không lưu trữ trong bản đồ. Vì vậy, kiểm tra nếu một khóa trong bản đồ có thể đạt được bằng cách so sánh nó với nil.
Sử dụng "kỹ thuật" này cũng có một lợi thế khác: bạn có thể kiểm tra sự tồn tại của nhiều khóa theo cách nhỏ gọn (bạn không thể làm điều đó với biểu mẫu "dấu phẩy ok" đặc biệt). Thông tin thêm về điều này: Kiểm tra xem khóa có tồn tại trong nhiều bản đồ trong một điều kiện không
Lấy giá trị 0 của loại giá trị khi lập chỉ mục với khóa không tồn tại cũng cho phép chúng tôi sử dụng bản đồ với boolcác giá trị thuận tiện dưới dạng bộ . Ví dụ:
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")
}
Nó xuất ra (thử trên Sân chơi Go ):
Contains 'one': true
'two' is in the set
'three' is not in the set
Xem liên quan: Làm thế nào tôi có thể tạo một mảng có chứa các chuỗi duy nhất?
Ttrong var v, ok T = a[x]? không okphải là bool?
map[bool]boolvà Tlà bool, nhưng nó cũng hoạt động nếu bản đồ là loại map[interface{}]boolvà Tlà interface{}; hơn nữa, nó cũng hoạt động với các loại tùy chỉnh có boolkiểu cơ bản, xem tất cả trên Sân chơi Go . Vì vậy, vì hình thức đó là hợp lệ với nhiều loại được thay thế cho T, đó là lý do tại sao cái chung Tđược sử dụng. Loại okcó thể là bất cứ thứ gì mà một unypedbool có thể được chỉ định.
cách tốt hơn ở đây
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)
Sau đó, đi chạy maps.go somestring tồn tại? đúng không tồn tại? sai
_, ok = m["somestring"]nên là=_, ok := m["somestring"]
Nó được đề cập dưới "Biểu thức chỉ mục" .
Biểu thức chỉ mục trên bản đồ a bản đồ loại [K] V được sử dụng trong gán hoặc khởi tạo biểu mẫu đặc biệt
v, ok = a[x] v, ok := a[x] var v, ok = a[x]mang lại một giá trị boolean chưa được bổ sung. Giá trị của ok là đúng nếu khóa x có trong bản đồ và ngược lại là sai.
Một phép gán hai giá trị có thể được sử dụng cho mục đích này. Vui lòng kiểm tra chương trình mẫu của tôi dưới đây
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")
}
}