الدرس 10 من 10
القواميس وLINQ
- 15 دقيقة
- 5 فحوص
- 3 تلميحات
- إلى المطلوب
هدف الدرس
العدّ بـ Dictionary والاستعلام بـ LINQ
الشرح
يربط القاموس Dictionary<string, int> كل مفتاح بقيمة، فبعد var gold = new Dictionary<string, int>(); يضيف السطر gold["ليان"] = 50; المفتاح إن لم يكن موجودًا، أو يستبدل قيمته إن كان موجودًا. لكن قراءة مفتاح غير موجود ترمي KeyNotFoundException، ولهذا يتوقّف البرنامج عند gold["سارة"]++ في أول مرّة. فتأكّد أوّلًا بـ ContainsKey، أو استعمل TryGetValue(key, out int value) التي تُرجع هل وُجد المفتاح وتضع قيمته في value أو تضع صفرًا، وهو نمط Try نفسه الذي رأيته في درس الدوال.
وتعطيك LINQ من System.Linq دوال جاهزة تسأل بها أي مجموعة، وكل واحدة منها تأخذ دالة قصيرة تُكتب بسهم (lambda)، فـ Where(x => x > 10) تُبقي العناصر التي تحقّق الشرط، وSelect(x => x * 2) تحوّل كل عنصر، وOrderBy ترتّب تصاعديًّا وOrderByDescending ترتّب تنازليًّا، وSum() تجمع، وCount(x => ...) تعدّ العناصر التي تحقّق الشرط. ويمكنك أن تستدعيها متتالية هكذا: scores.Where(s => s >= 50).OrderBy(s => s).ToList().
والقاموس مجموعة من الأزواج، لكل زوج منها Key وValue، فتعمل عليه LINQ كما تعمل على القائمة، وValues تعطيك قيمه وحدها. واعلم أن الاستعلام لا يُنفَّذ حين تكتبه بل حين تمرّ على نتيجته، فإذا تغيّرت المجموعة بين الوقتين تغيّرت النتيجة، أما ToList() فتنفّذه في الحال وتحفظ النتيجة في قائمة.
المطلوب
أكمل CountKills(kills) لتُرجع قاموسًا فيه عدد مرّات قتل كل نوع من الأعداء في السجلّ، وKillsOf(kills, name) لتعدّ بـ Count مرّات قتل نوع واحد، وTotalKills(counts) لتجمع قيم القاموس بـ Sum. ثم أكمل Report(counts, min) لتُرجع قائمة نصوص بالشكل "عفريت: 3" لكل نوع قُتل min مرّات أو أكثر، مرتّبة من الأكثر إلى الأقلّ، باستعمال Where وOrderByDescending وSelect.
الفحوص
5 فحوص- الدالة CountKills تعدّ كل نوع
- الدالة KillsOf تعدّ نوعًا واحدًا، وتُرجع صفرًا لنوع لم يُقتل
- الدالة TotalKills تجمع قيم القاموس
- الدالة Report تُبقي ما بلغ min وترتّب من الأكثر بالشكل «عفريت: 5»
- الدالتان CountKills ثم Report تعملان معًا على سجلّ كامل