الوصول إلى القيم
جزء من قسم Logic & Flow في رحلة Rust على Coddy — الدرس 30 من 66.
بمجرد أن يكون لديك بيانات مخزنة في hash map الخاص بك، ستحتاج إلى طريقة لاستعادتها. تسمح لك الطريقة .get() بالبحث عن قيمة باستخدام مفتاحها:
let value = my_map.get("some_key");ومع ذلك، هناك تفصيل مهم يجب فهمه: لا يقوم .get() بإرجاع القيمة مباشرة. بدلاً من ذلك، فإنه يعيد نوع Option — وهو نوع مدمج في لغة Rust يمثل إما وجود قيمة (Some) أو غيابها (None). وذلك لأن المفتاح الذي تبحث عنه قد لا يكون موجوداً في الـ hash map.
عندما يكون المفتاح موجوداً، تعيد الدالة .get() القيمة Some(&value) - لاحظ الرمز &، مما يعني أنك تحصل على مرجع (reference) للقيمة. عندما لا يكون المفتاح موجوداً، فإنها تعيد None:
match capitals.get("France") {
Some(capital) => println!("The capital is {}", capital),
None => println!("Country not found"),
}في ذراع المطابقة (match arm) الخاص بـ Some(capital)، تتعامل لغة Rust مع المرجع تلقائياً نيابة عنك — capital هنا مرتبط بالقيمة المرجعية الداخلية، لذا لا تحتاج إلى كتابة & بشكل صريح في النمط (pattern).
هذا التصميم يمنع برنامجك من الانهيار عندما تحاول الوصول إلى مفتاح غير موجود. فبدلاً من التسبب في خطأ، تجبرك Rust على التعامل مع كلا الاحتمالين - العثور على القيمة أو عدم العثور عليها - مما يجعل الكود الخاص بك أكثر قوة وقابلية للتنبؤ.
التحدي
سهلستتلقى مدخلين: اسم دولة واسم عاصمة. قم بإنشاء خريطة تجزئة (hash map) تخزن أسماء الدول كمفاتيح (من نوع String) وعواصمها كقيم (من نوع String). أدخل الدولة وعاصمتها في خريطة التجزئة. بعد ذلك، ستتلقى مدخلاً ثالثاً يحتوي على اسم دولة أخرى للبحث عنها. استخدم التابع .get() لاسترداد العاصمة لهذه الدولة وتعامل مع كلتا الحالتين: عندما تكون الدولة موجودة في الخريطة وعندما لا تكون موجودة.
ملاحظة: التابع .get() يعيد Option — إما Some(&value) (مرجع للقيمة) عندما يكون المفتاح موجوداً، أو None عندما لا يكون موجوداً. في ذراع match، يمكنك كتابة Some(capital) وسيقوم Rust تلقائياً بالتعامل مع المرجع نيابة عنك، لذا يمكنك استخدام capital مباشرة في جملة الطباعة الخاصة بك.
المتطلبات:
- استيراد
HashMapمنstd::collections - إنشاء خريطة تجزئة قابلة للتعديل (mutable) بأنواع
HashMap<String, String> - قراءة المدخل الأول كاسم للدولة
- قراءة المدخل الثاني كاسم للعاصمة
- إدراج الدولة والعاصمة في خريطة التجزئة
- قراءة المدخل الثالث كالدولة المراد البحث عنها
- استخدام
.get()لاسترداد العاصمة للدولة المراد البحث عنها - استخدام
matchللتعامل مع الـOptionالذي يعيده.get() - إذا تم العثور على الدولة، اطبع:
The capital of [country] is [capital] - إذا لم يتم العثور على الدولة، اطبع:
[country] not found in the map
المدخلات:
- السطر الأول: اسم الدولة المراد إدراجها (على سبيل المثال،
France) - السطر الثاني: اسم العاصمة (على سبيل المثال،
Paris) - السطر الثالث: اسم الدولة المراد البحث عنها (على سبيل المثال،
FranceأوGermany)
المخرجات:
- إذا كانت الدولة المبحوث عنها موجودة:
The capital of [country] is [capital] - إذا كانت الدولة المبحوث عنها غير موجودة:
[country] not found in the map
ورقة مرجعية
تسترجع الطريقة .get() قيمة من خريطة التجزئة (hash map) باستخدام مفتاحها:
let value = my_map.get("some_key");تعيد الطريقة .get() نوع Option لأن المفتاح قد لا يكون موجوداً في خريطة التجزئة:
- عندما يكون المفتاح موجوداً: تعيد
Some(&value)(مرجع للقيمة) - عندما لا يكون المفتاح موجوداً: تعيد
None
استخدم match للتعامل مع كلتا الحالتين:
match capitals.get("France") {
Some(capital) => println!("The capital is {}", capital),
None => println!("Country not found"),
}يمنع هذا التصميم حدوث أعطال (crashes) عند الوصول إلى مفاتيح غير موجودة من خلال إجبارك على التعامل مع كلا الاحتمالين.
جرّب بنفسك
use std::collections::HashMap;
use std::io;
fn main() {
// قراءة اسم الدولة لإدراجها
let mut country = String::new();
io::stdin().read_line(&mut country).expect("Failed to read line");
let country = country.trim().to_string();
// قراءة اسم العاصمة
let mut capital = String::new();
io::stdin().read_line(&mut capital).expect("Failed to read line");
let capital = capital.trim().to_string();
// قراءة اسم الدولة للبحث عنها
let mut lookup_country = String::new();
io::stdin().read_line(&mut lookup_country).expect("Failed to read line");
let lookup_country = lookup_country.trim().to_string();
// TODO: اكتب كودك أدناه
// قم بإنشاء HashMap، وأدرج الدولة والعاصمة، ثم ابحث عن الدولة
}يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Logic & Flow
1تدفق التحكم المتقدم
تعبير 'match'مطابقة قيم متعددةمطابقة النطاقاتتعبير 'if let'الحلقات التكرارية كتعبيراتمراجعة - محلل أوامر بسيط4تجميع البيانات باستخدام Structs
ما هو الـ Struct؟نظرة عامة على الـ Structsالوصول إلى حقول الـ Structالـ Structs القابلة للتعديلالـ Structs كمعاملات للدوالالـ Tuple Structsمراجعة - إنشاء Book Struct7معالجة الأخطاء باستخدام 'Result'
ما هو 'Result'؟استخدام 'match' مع 'Result'is_ok() و is_err()اختصارات: unwrap و expectعامل علامة الاستفهام '?'تحويل السلاسل النصية إلى أرقامملخص - دالة القسمة الآمنة10الـ Closures والدوال المجهولة
ما هو الـ Closure؟تعريف Closure بسيطالـ Closures مع المعاملاتالتقاط البيئة المحيطةملخص - Closure الجامع البسيط2مقدمة في الـ Vectors
ما هو الـ Vector؟إنشاء Vectorإضافة عناصر باستخدام pushالوصول إلى عناصر الـ Vectorالتكرار عبر الـ Vectorالتكرار القابل للتعديل (Mutable Iteration)إزالة العناصرمراجعة - متتبع نقاط بسيط5أزواج (المفتاح والقيمة) مع Hash Maps
ما هو Hash Map؟إنشاء Hash Mapإدراج أزواج (المفتاح والقيمة)الوصول إلى القيمالتكرار عبر Hash Mapتحديث قيمةإزالة زوجملخص - عداد الكلمات6التعامل مع غياب القيم باستخدام 'Option'
ما هو الـ 'Option'؟استخدام 'match' مع 'Option''is_some()' و 'is_none()'فك تغليف الـ 'Option'الدالة 'expect'توفير قيمة افتراضية: 'unwrap_or'مراجعة - البحث عن عنصر9شرائح الـ String والمزيد
String مقابل &strإنشاء شرائح الـ Stringالشرائح كمعاملات للدوالشرائح أخرىمراجعة - إيجاد الكلمة الأولى