أعلم أنه يمكنني التكرار على خريطة m
بواسطة ،
for k, v := range m { ... }
وابحث عن المفتاح ولكن هل هناك طريقة أكثر فاعلية لاختبار وجود المفتاح في الخريطة؟
لم أتمكن من العثور على الإجابة في spec spec .
إجابة سطر واحد:
if val, ok := dict["foo"]; ok {
//do something here
}
يمكن أن تتضمن عبارات if
في Go كلاً من الشرط وبيان التهيئة. المثال أعلاه يستخدم كلا:
تهيئة اثنين من المتغيرات - val
ستتلقى إما قيمة "foo" من الخريطة أو "قيمة صفرية" (في هذه الحالة السلسلة الفارغة) و ok
ستتلقى منطقيًا سيتم تعيينه على true
في حالة وجود "foo" بالفعل في الخريطة
يقيم ok
، والذي سيكون true
إذا كان "foo" في الخريطة
إذا كانت "foo" موجودة بالفعل في الخريطة ، فسيتم تنفيذ نص العبارة if
و val
ستكون محلية لهذا النطاق.
تحرير: الإجابة التالية تسبق Go 1. بدءًا من Go 1 ، لم تعد دقيقة/صالحة.
بالإضافة إلى مواصفات لغة برمجة Go ، يجب عليك قراءة الانتقال الفعال . في القسم الموجود على الخرائط كما يقولون ، من بين أشياء أخرى:
"ستؤدي محاولة جلب قيمة خريطة باستخدام مفتاح غير موجود في الخريطة إلى تعطل البرنامج ، ولكن هناك طريقة للقيام بذلك بأمان باستخدام مهمة متعددة."
var seconds int
var ok bool
seconds, ok = timeZone[tz]
"لاختبار التواجد في الخريطة دون القلق بشأن القيمة الفعلية ، يمكنك استخدام المعرف الفارغ ، الشرطة السفلية البسيطة (_). يمكن تعيين معرف فارغ أو إعلانه بأي قيمة من أي نوع ، مع تجاهل القيمة دون أي ضرر. لاختبار التواجد في خريطة ، استخدم المعرف الفارغ بدلاً من المتغير المعتاد للقيمة. "
_, present := timeZone[tz]
تم البحث في قائمة البريد الإلكتروني الخاصة بـ go -uts ووجدت حلاً تم إرساله بواسطة Peter Froehlich بتاريخ 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 موجودًا ، فسيتم تعيين الثواني بشكل مناسب وستكون "موافق" صحيحة ؛ إذا لم يكن كذلك ، فسيتم تعيين الثواني على صفر وستكون "موافق" خاطئة. فيما يلي وظيفة تضعها مع تقرير خطأ Nice:
func offset(tz string) int { if seconds, ok := timeZone[tz]; ok { return seconds } log.Println("unknown time zone:", tz) return 0 }
لاختبار التواجد في الخريطة دون القلق بشأن القيمة الفعلية ، يمكنك استخدام المعرف الفارغ (_) بدلاً من المتغير المعتاد للقيمة.
_, present := timeZone[tz]
كما لاحظت إجابات أخرى ، فإن الحل العام هو استخدام تعبير index في واجب للنموذج الخاص:
v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]
var v, ok T = a[x]
هذا لطيف ونظيف. لديها بعض القيود على الرغم من: يجب أن يكون إحالة شكل خاص. يجب أن يكون تعبير الجانب الأيمن عبارة عن تعبير فهرس الخريطة فقط ، ويجب أن تحتوي قائمة تعبير الجانب الأيسر على معامَنين بالضبط ، أولًا يكون نوع القيمة قابلاً للتخصيص ، وثانيًا يمكن تعيين قيمة 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
.
استخدام هذه "التقنية" له ميزة أخرى أيضًا: يمكنك التحقق من وجود مفاتيح متعددة بطريقة مدمجة (لا يمكنك القيام بذلك باستخدام النموذج "فاصلة موافق" الخاص). المزيد عن هذا: التحقق من وجود المفتاح في خرائط متعددة في حالة واحدة
طريقة أفضل هنا
if _, ok := dict["foo"]; ok {
//do something here
}
يذكر تحت "تعبيرات الفهرس" .
تعبير فهرس على خريطة a of type map [K] V يستخدم في مهمة أو تهيئة للنموذج الخاص
v, ok = a[x] v, ok := a[x] var v, ok = a[x]
تعطي قيمة منطقية إضافية غير نمطية. تكون قيمة "موافق" صحيحة إذا كان المفتاح x موجودًا في الخريطة ، وكان غير صحيح.
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)
ثم ، انتقل تشغيل maps.go 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")
}
}