أستمع الى المقال

شرحنا في الدرسين السابقين، نوعين من التجميعات في كوتلن. تعرفنا فيهما على النوع القوائم Lists، وكيفية استخدامه في تجميع عناصر (كائنات) من نوع بيانات معين معًا. وقلنا أيضًا أن الترتيب فيه مهم ويمكن أن تتكرر فيه العناصر في القائمة. خلاف النوع الأطقم Set والذي يكون فيه ترتيب العناصر غير مهم ولا يسمح بتكرار العناصر في التجميعة. 

في هذا الدرس، سنتعرف على النوع الثالث من التجميعات، النوع Map.

ماهي الخرائط Maps:

الـ Map هي عبارة عن تجميعة يتم تخزين الكائنات فيها على شكل أزواج Pairs من (المفاتيح Keys والقيم Values). أي أننا نضع مفتاح لكل قيمة، ويكون الإثنان معًا عبارة عن عنصر واحد في التجميعة.

تؤدي المفاتيح في الـ Map، نفس عمل الفهرس Index في القائمة List. الفرق أن فهرس القائمة يتم إنشاؤه تلقائيًا مع إضافة كل عنصر للقائمة. ويكون من نوع الأعداد الصحيحة Int الموجبة ويبدأ من الصفر. أما المفاتيح في الـ Map نحن من يجب أن نضعها. ويمكن أن تكون من أي نوع من أنواع البيانات، مثل: String، Int وغيرها، وليس الأعداد الصحيحة Int فقط. 

إذًا، هي عبارة عن فهرس خاص، من نوع بيانات معين. ولأنها تُشير إلى قيمة معينة، يجب أن تكون فريدة في التجميعة، حتى تُمثل هذه القيمة فقط. ولكن يمكن تكرار القيم، أي يمكن حفظ نفس القيمة، في مفاتيح مختلفة.

إنشاء الـ Map:

تمامًا مثل النوعين السابقين، تتوفر لها دالة تمكننا من إنشاءها:

val map = mapOf<DataType, DataType>(key to value)

وضعنا نوعي بيانات بين قوسي الزاوية < >، تفصلهما فاصلة ( , ). النوع الأول هو نوع المفتاح، والثاني هو نوع القيمة. ثم في أقواس الدالة ( )، وضعنا عنصر واحد يتكون من المفتاح والقيمة، وبينهما الكلمة المفتاحية to.

فمثلًا، إذا أردنا إنشاء تجميعة لكائنات من الخضروات مع أسعارها. فهنا يمكننا جعل المفتاح هو اسم كائن الخُضْرة، ﻷنه ثابت وفريد لكل نوع خضروات. والقيمة هي سعر الخُضْرة، ﻷنها من الممكن أن تتكرر مع كائن آخر:

val vegetables = mapOf<String, Int>(“Carrots” to 15, “Okra” to 10, “Potatoes” to 15)

تحتوي تجميعة vegetables، على ثلاث عناصر. كل عنصر يتكون من مفتاح من نوع البيانات النصي String، وقيمة من نوع البيانات العددي Int. ونلاحظ أن المفاتيح فريدة وغير متكررة، أما قيمة السعر 15 تكررت مرتين.

الاستدلال على نوعي بيانات المفتاح والقيمة:

وكما تعودنا في كوتلن، يمكننا اختصار الشفرة بالتخلي عن ذكر نوع البيانات للمفتاح والقيمة صراحةً، ﻷن كوتلن ستستنتج نوعيهما:

val vegetables = mapOf(“Carrots” to 15, “Okra” to 10, “Potatoes” to 15)

أي الطريقتين اتبعنا، ستكون نتيجة طباعة تجميعة vegetables، عند وضع المتغير في دالة الطباعة ()println، كالتالي:

{Carrots=15, Okra=10, Potatoes=15}

الوصول إلى عناصر الـ Map:

يتم الوصول إلى عناصر الـ Map، باستخدام المفتاح الذي يُمثلها. باستخدام دالة ()get، أو أقواس الفهرس المربعة [ ]. تمامًا مثل القوائم Lists. فمثلًا للحصول على سعر البامية Okra، يمكننا فعل التالي:

println(vegetables.get(“Okra”))

أو

println(vegetables[“Okra”])

بدلًا أن نضع رقم الفهرس الذي يُمثل قيمة العنصر، بين قوسي الفهرس المربعين [  ]، كما نفعل في تجميعة الـ List. للوصول لقيمة العنصر في Map، نضع المفتاح الذي وضعناه بأنفسنا في التجميعة. وسيتم طباعة 10، والتي هي قيمة العنصر.

الخصائص والدوال:

بالإضافة إلى دالة ()get، يمكننا استخدام خاصية size، ودالة ()isEmpty مع الـ Map. وأيضًا، دالتي ()containsKey لمعرفة إذا كان مفتاح ما متوفرًا في التجميعة، ودالة ()containsValue لمعرفة أن التجميعة تحتوي على قيمة ما.

إذا طبقنا كل هؤلاء على تجميعة الخضروات vegetables، ستكون النتيجة:

وستكون نتيجة الشفرة عند تنفيذها:

خرائط قابلة للتغيير Mutable Maps:

عند إنشاء تجميعة باستخدام دالة ()mapOf، نحصل تلقائيًا على نوع Map ثابت غير قابل للتغيير Immutable Map. أما إذا أردنا تجميعة مرنة نستطيع الإضافة إليها والحذف منها وتغيير عناصرها، سنقوم بإنشائها عبر استخدام دالة ()mutableMapOf:

val vegetables = mutableMapOf(“Carrots” to 15)

دوال إضافية للخرائط القابلة للتغيير:

كل الدوال السابقة التي استخدمناها مع نوع الـ Map الثابت، يمكننا استخدامها مع هذا النوع، بالإضافة إلى دوال لإجراء عمليات الإضافة والحذف وغيرها. مثل: دالة (put(key, value لإضافة عنصر جديد للتجميعة، والتي يمكننا أيضًا كتابتها مثل: mutableMap[key] = value. ودالة (putAll(Map لإضافة تجميعة كاملة لتجميعة أخرى. و (remove(key والتي نُرسل لها مفتاح للعنصر لحذفه. و ()clear لحذف كل عناصر التجميعة:

بعد تنفيذ الشفرة أعلاه، ستكون النتيجة:

يمكن إيجاد كل الخصائص والدوال التي يمكننا استخدامها مع Map، في هذا الرابط من موقع كوتلن الرسمي.

الدوران على عناصر الـ Maps:

للتعامل مع عناصر التجميعة كل على حدى، يمكننا استخدام حلقة التكرار for للدوران عليها:

داخل الحلقة، وضعنا متغير vege وهو سيُمثل عنصر واحد من التجميعة في كل دورة للحلقة، بدءاً من العنصر الأول وحتى الأخير. وﻷنه عنصر من تجميعة Map، فهو يتكوّن من مفتاح وقيمة. لذا عند الطباعة، طلبنا مفتاح العنصر باستخدام الخاصية key، وقيمة العنصر باستخدام الخاصية value.

وستكون نتيجة تنفيذ الشفرة:

ويمكننا أيضًا استخدام طريقة أخرى:

داخل حلقة for، فتحنا قوسين آخرين ووضعنا بهما متغيرين مفصولين بفاصلة ( , ). المتغير الأول سيُمثل مفتاح العنصر، والمتغير الثاني سيُمثل قيمة العنصر. يمكننا تسمية المتغيرين كما نريد. وستكون نتيجة التنفيذ هي نفسها.

برنامج تجميعة خضروات وأسعارها:

لفهم المعلومات التي وردت في هذا الدرس، دعونا نقوم بكتابة برنامج بسيط، يستقبل معلومات عن الخضروات وأسعارها. يمكننا بالطبع استخدام القوائم Lists في البرنامج، ولكن عندها سنحتاج لقائمتين: واحدة لأسماء الخضروات، والثانية ﻷسعارها. ثم لطباعة قيمة سعر كائن خُضْرة واحد، سنبحث أولًا في قائمة الأسماء، ثم سنبحث مرة أخرى في قائمة الأسعار. هذه لا تبدو طريقة مثالية، خاصة إذا توفرت لدينا طريقة أفضل وأقل شفرة.

لذا بدلًا عن استخدام القوائم، يمكننا استخدام الـ Map:

ولفهم الشفرة، فلنلقي نظرة على الصورة أدناه:

  1. بدأنا البرنامج بإنشاء تجميعة Map قابلة للتغيير وأسميناها vegetables. وجعلنا نوع بيانات مفاتيح العناصر من النوع String، ونوع بيانات قيم العناصر من النوع Int.
  2. طباعة رسالة للمستخدم، تطلب منه إدخال أسماء الخضروات وأسعارها، والفصل بينها بفاصلة ( , )، وإدخال الكلمة stop عند الانتهاء. ثم نقرأ مدخلات المستخدم عبر دالة ()readln، ونخزنها في المتغير input، ﻷننا نريد التعامل مع هذا المتغير لاحقًا في حلقة while.
  3. في حلقة while، نضع شرط إذا لم تكن المدخلات التي حفظناها في المتغير input، تساوي الكلمة stop، نفذ الشفرة داخل الحلقة. الشفرة داخل الحلقة، تقوم بتقسيم قيمة input (المدخلات) عبر استخدام دالة ()split، والتي ستعيد لنا المدخل قبل الفاصلة ( , ) منفصل عن الذي بعدها. ثم نخزن كل مدخل في متغير منفصل. وفي آخر سطر في الحلقة، نعيد قراءة المدخلات ونحفظها في المتغير input. يمكن تغيير قيمة المتغير، ﻷننا أعلناه كمتغير var. ولن تتوقف حلقة while عن الدوران، حتى تكون قيمة input تساوي stop.
  4. لطباعة مفاتيح وقيم عناصر التجميعة، نستخدم الحلقة for، ونطبعها الواحدة تلو الأخرى. استخدمنا متغير x، لطباعة أرقام متسلسلة. (تم شرح هذا الأمر في درس الفرق بين ال Expressions و ال Statements).
  5. عند تنفيذ البرنامج، سيطلب من المستخدم إدخال قائمة الخضروات وأسعارها. مدخلات المستخدم تظهر باللون الأخضر في تبويب Run في برنامج IntelliJ.
  6. النتيجة النهائية لعمل حلقة for.

هذا الدرس هو جزء من سلسلة تعليم مبادئ البرمجة بلغة كوتلن. لمُتابعة الدروس منذ البداية ومُشاهدة فهرس المحتويات يمكنك الانتقال إلى الدرس الأول من هنا.

هل أعجبك المحتوى وتريد المزيد منه يصل إلى صندوق بريدك الإلكتروني بشكلٍ دوري؟
انضم إلى قائمة من يقدّرون محتوى إكسڤار واشترك بنشرتنا البريدية.