Programming Basics SQL HTML CSS JavaScript React Python C++ Java JavaFX Swing Problem Solving English English Conversations Computer Fundamentals Linux Learn Typing

C++الكلاس map

  • تعريف الكلاس map
  • دوال الكلاس map
  • أمثلة شاملة حول التعامل مع الكلاس map

تعريف الكلاس map

يستخدم لإنشاء كائن يمثل حاوية تخزن العناصر التي نضيفها فيها بشكل جدول يتألف من عمودين حيث يتكون كل عنصر من مفتاح ( Key ) يوضع في العمود الأول و قيمة ( Value ) توضع في العمود الثاني بالإضافة إلى أنها ترتب العناصر بشكل تصاعدي على حسب قيم المفاتيح كالتالي.



القيمة المفتاحية لكل عنصر يمكن أن تكون من أي نوع تريده, و لكن في أغلب الأوقات ستكون المفاتيح عبارة عن أعداد أو كلمات.
لا تستطيع وضع نفس القيمة المفتاحية لأكثر من عنصر و هذا شيء منطقي لأن المفاتيح هي ما يميز العناصر عن بعضها.


لاستخدام الكلاس map - أي حتى تتمكن من إنشاء كائنات منه - يجب تضمين الملف #include<map> لأنه موجود فيه.


بناء الكلاس

template < class Key,                                     // map::key_type
           class T,                                       // map::mapped_type
           class Compare = less<Key>,                     // map::key_compare
           class Alloc = allocator<pair<const Key,T> >    // map::allocator_type
           > class map;

إذاً عند إنشاء كائن من الكلاس map يجب أن نمرر له نوع المفاتيح التي نريد تخزينها فيه مكان الباراميتر Key و نوع القيم التي نريد تخزينها فيه مكان الباراميتر T.

دوال الكلاس map

الجدول التالي يحتوي على دوال الكلاس map التي تستخدم للحصول على عداد يتيح المرور على عناصره.

الدالة مع تعريفها
1 iterator begin() ترجع كائن iterator يشير لمكان أول عنصر في الكائن الذي قام باستدعائها.
إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر و الوقوف عند آخر عنصر.
2 iterator end() ترجع كائن iterator يشير لمكان آخر عنصر في الكائن الذي قام باستدعائها.
إذا كنا ننوي استخدام الدالة begin() بداخل حلقة فإننا نستخدم معها الدالة end() من أجل البدء من أول عنصر و الوقوف عند آخر عنصر.
3 iterator rbegin() ترجع كائن iterator يشير لمكان آخر عنصر في الكائن الذي قام باستدعائها.
إذا كنا ننوي استخدام الدالة rbegin() بداخل حلقة فإننا نستخدم معها الدالة rend() من أجل البدء من آخر عنصر و الوقوف عند أول عنصر.
4 iterator rend() ترجع كائن iterator يشير لمكان أول عنصر في الكائن الذي قام باستدعائها.
إذا كنا ننوي استخدام الدالة rbegin() بداخل حلقة فإننا نستخدم معها الدالة rend() من أجل البدء من آخر عنصر و الوقوف عند أول عنصر.

الجدول التالي يحتوي على دوال الكلاس map التي تستخدم للحصول على عدد عناصره.

الدالة مع تعريفها
1 bool empty() تستخدم لمعرفة ما إن كان الكائن الذي قام باستدعائها فارغاً أم لا.
ترجع false في حال كان يوجد فيه عنصر أو أكثر, و ترجع true إن لم يكن كذلك.
2 size_t size() تستخدم للحصول على عدد العناصر الموجودة في الكائن الذي قام باستدعائها.
3 size_t max_size() تستخدم للحصول على أكبر عدد عناصر يمكن تخزينها في الكائن الذي قام باستدعائها.

الجدول التالي يحتوي على دوال الكلاس map التي تستخدم للوصول لقيم عناصره.

الدالة مع تعريفها
1 mapped_type& at(key_type& k) تستخدم للوصول لقيمة عنصر محدد في الكائن الذي قام باستدعائها سواء لتغييرها أو للحصول عليها.
مكان الباراميتر k نمرر لها مفتاح العنصر الذي نريد الوصول إليه.
ترمي الإستثناء out_of_range في حال كانت قيمة k لا تمثل القيمة المفتاحية لأي عنصر موجود في الكائن.

معلومة: يمكنك استخدام العامل [] للوصول للعنصر و لكن عليك معرفة أن استخدام هذا العامل لا يرمي إستثناء في حال تمرير قيمة مفتاح غير موجود في الكائن.
2 operator[] (key_type& k) يستخدم العامل [] للوصول لقيمة عنصر محدد في الكائن الذي قام باستدعائها سواء لتغييرها أو للحصول عليها.
مكان الباراميتر k نمرر لها مفتاح العنصر الذي نريد الوصول إليه.
في حال تمرير قيمة مفتاح غير موجود مكان الباراميتر k سيتم إضافة العنصر كعنصر جديد في الكائن.

الجدول التالي يحتوي على دوال الكلاس map التي تستخدم للتحكم بعناصره.

الدالة مع تعريفها
1 pair<K, V> insert({key, value}) تستخدم لإضافة عنصر جديد في الكائن الذي قام باستدعائها.
مكان الباراميتر key نمرر القيمة المفتاحية للعنصر الذي نريد إضافته.
مكان الباراميتر value نمرر القيمة التي نريد وضعها في العنصر الذي سيتم إضافته.
كما أنها ترجع نسخة من العنصر الذي تم إضافته.
2 pair<K, V> emplace(Args&&... args) تستخدم لإضافة عنصر جديد في الكائن الذي قام باستدعائها تماماً كالدالة insert().
مكان الباراميتر Args نمرر القيمة المفتاحية للعنصر الذي نريد إضافته ثم نضع فاصلة و نمرر القيمة التي نريد وضعها فيه.
كما أنها ترجع نسخة من العنصر الذي تم إضافته.
3 size_t erase(key_type& k) تستخدم لحذف عنصر محدد من الكائن الذي قام باستدعائها من خلال المفتاح الخاص به.
مكان الباراميتر k نمرر مفتاح العنصر الذي نريد حذفه.
4 iterator erase(const_iterator position) تستخدم لحذف عنصر محدد من الكائن الذي قام باستدعائها من خلال الإشارة إلى مكانه فيه.
مكان الباراميتر position نمرر كائن أصله من Iterator يشير لعنوان العنصر الذي سيتم حذفه.
5 iterator erase(const_iterator first, const_iterator last) تستخدم لحذف مجموعة عناصر من الكائن الذي قام باستدعائها من خلال الإشارة إلى مكان وجود هذه العناصر.
مكان الباراميتر first نمرر كائن أصله من const_iterator يشير لعنوان العنصر الذي سيتم بدء الحذف من عنده.
مكان الباراميتر last نمرر كائن أصله من const_iterator يشير لعنوان العنصر الذي سيتم إيقاف الحذف عنده.
6 void swap(map& anotherMap) تستخدم لتبديل قيم عناصر الكائن الذي قام باستدعائها بقيم عناصر الكائن الذي نمرره لها.
مكان الباراميتر anotherMap نمرر لها كائن من الكلاس map يملك نفس نوع عناصر الكائن الذي قام باستدعائها.

الجدول التالي يحتوي على دوال الكلاس map التي تستخدم للبحث فيه.

الدالة مع تعريفها
1 size_t count(T& val) تستخدم للبحث في الكائن الذي قام باستدعائها عن عنصر يملك قيمة محددة.
مكان الباراميتر val نمرر القيمة التي نريد البحث عنها.
في حال تم إيجاد عنصر يملك نفس القيمة التي تم تمريرها لها ترجع القيمة 1 و في حال لم يتم إيجاد عنصر يملك نفس القيمة ترجع القيمة 0.
2 iterator find(const T& val) تستخدم للبحث في الكائن الذي قام باستدعائها عن عنصر يملك قيمة محددة.
مكان الباراميتر val نمرر القيمة التي نريد البحث عنها.
في حال تم إيجاد عنصر يملك نفس القيمة التي تم تمريرها لها ترجع كائن من Iterator يشير لعنوان العنصر في الذاكرة.
و في حال لم يتم إيجاد عنصر يملك نفس القيمة التي تم تمريرها لها ترجع كائن من Iterator قيمته تساوي القيمة التي ترجعها الدالة end().

أمثلة شاملة حول التعامل مع الكلاس map

في كل مثال موضوع قمنا باستخدام دوال جديدة حتى تعرف كيف تستخدم جميع الدوال التي ذكرناها في الجدول.


في المثال التالي قمنا بتعريف كائن من map مع تحديد أن عناصره تتكون من مفاتيح نوعها string قيم و نوعها string أيضاً.
بعدها قمنا بإضافة بعض العناصر فيه, كل عنصر عبارة منهم عبارة عن كود الإتصال الخاص بالبلد و إسم البلد.
بعدها قمنا بطباعة عدد العناصر التي قمنا بإضافتها.
في الأخير قمنا بعرض جميع مفاتيح و قيم العناصر الموجودة فيه بواسطة حلقة.

ملاحظة: قمنا باستخدام الدالة emplace() لإضافة العناصر, الدالة size() لمعرفة عدد العناصر التي تم إضافتها. عند عرض جميع قيم عناصر الكائن, قمنا باستخدام الدالة begin() للحصول على مؤشر للعنصر الأول لأننا سنبدأ من عنده و الدالة end() للحصول على مؤشر للعنصر الأخير لأننا سنتوقف عنده.

المثال الأول

main.cpp
#include <iostream>
#include <map>

using namespace std;

int main()
{
    // string و قيم نوعها string يمكنه أن يحتوي على مفاتيح نوعها map هنا قمنا بتعريف كائن من الكلاس
    map<string, string> myMap;

    // كل عنصر يحتوي على كود البلد كمفتاح و إسمه كقيمة ,myMap هنا قمنا بإضافة 12 عنصر في الكائن
    myMap.emplace("+961", "Lebanon");
    myMap.emplace("+962", "Jordan");
    myMap.emplace("+963", "Syria");
    myMap.emplace("+964", "Iraq");
    myMap.emplace("+965", "Kuwait");
    myMap.emplace("+966", "KSA");
    myMap.emplace("+967", "Yaman");
    myMap.emplace("+968", "Oman");
    myMap.emplace("+970", "Palestine");
    myMap.emplace("+212", "Morocco");
    myMap.emplace("+281", "Libya");
    myMap.emplace("+20",  "Egypt");
    
    // size() باستخدام الدالة myMap هنا قمنا بطباعة عدد عناصر الكائن
    cout << "myMap size = " << myMap.size() << "\n\n";
    
    cout << "myMap keys and values\n";
    cout << "---------------------\n";

    // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه myMap هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن
    for (auto it = myMap.begin(); it != myMap.end(); ++it)
    {
        // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية
        // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية
        cout << it->first << "\t | " << it->second << "\n";
    }

    return 0;
}

سنحصل على النتيجة التالية عند التشغيل.

myMap size = 12

myMap keys and values
---------------------
+20      | Egypt
+212     | Morocco
+281     | Libya
+961     | Lebanon
+962     | Jordan
+963     | Syria
+964     | Iraq
+965     | Kuwait
+966     | KSA
+967     | Yaman
+968     | Oman
+970     | Palestine


في المثال التالي قمنا بتعريف كائن من map مع تحديد أن عناصره تتكون من مفاتيح نوعها int قيم و نوعها string.
بعدها قمنا بعرض القيم الموجودة فيه بواسطة حلقة.

المثال الثاني

main.cpp
#include <iostream>
#include <map>

using namespace std;

int main()
{
    // string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها map هنا قمنا بتعريف كائن من الكلاس
    map<int, string> myMap = {
        {1, "One"},
        {2, "Two"},
        {3, "Three"},
        {4, "Four"},
        {5, "Five"},
    };
    
    // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه myMap هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن
    for (auto it = myMap.begin(); it != myMap.end(); ++it)
    {
        // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية
        // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية
        cout << it->first << " - " << it->second << "\n";
    }

    return 0;
}

سنحصل على النتيجة التالية عند التشغيل.

1 - One
2 - Two
3 - Three
4 - Four
5 - Five


في المثال التالي قمنا بتعريف كائن من map مع تحديد أن عناصره تتكون من مفاتيح نوعها int قيم و نوعها string.
بعدها قمنا بعرض القيم الموجودة فيه بشكل عكسي بواسطة حلقة.

ملاحظة: قمنا باستخدام الدالة rbegin() للحصول على مؤشر للعنصر الأخير لأننا سنبدأ من عنده و الدالة rend() للحصول على مؤشر للعنصر الأول لأننا سنتوقف عنده.

المثال الثالث

main.cpp
#include <iostream>
#include <map>

using namespace std;

int main()
{
    // string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها map هنا قمنا بتعريف كائن من الكلاس
    map<int, string> myMap = {
        {1, "One"},
        {2, "Two"},
        {3, "Three"},
        {4, "Four"},
        {5, "Five"},
    };
    
    // إبتداءاً من آخر عنصر وصولاً لأول عنصر فيه myMap هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن
    for (auto it = myMap.rbegin(); it != myMap.rend(); ++it)
    {
        // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية
        // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية
        cout << it->first << " - " << it->second << "\n";
    }

    return 0;
}

سنحصل على النتيجة التالية عند التشغيل.

5 - Five
4 - Four
3 - Three
2 - Two
1 - One


في المثال التالي قمنا بتعريف كائن من map مع تحديد أن عناصره تتكون من مفاتيح نوعها int قيم و نوعها string.
بعدها قمنا بالبحث عن عنصر يملك مفتاح محدد لمعرفة ما إن كان يوجد عنصر يملك هذا المفتاح أم لا مع الإشارة إلى أنه في حال وجود عنصر يملك هذا المفتاح سيتم طباعة قيمته أيضاً.

ملاحظة: قمنا باستخدام الدالة count() للبحث عن عنصر يملك مفتاح محدد في الكائن و قمنا باستخدام الدالة at() لطباعة قيمة العنصر الذي يملك مفتاح محدد.

المثال الرابع

main.cpp
#include <iostream>
#include <map>

using namespace std;

int main()
{
    // string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها map هنا قمنا بتعريف كائن من الكلاس
    map<int, string> myMap = {
        {1, "One"},
        {2, "Two"},
        {3, "Three"},
        {4, "Four"},
        {5, "Five"},
    };
    
    // يوجد فيه عنصر يملك مفتاح يساوي 4 أم لا myMap هنا قمنا بطباعة ما إن كان الكائن
    if (myMap.count(4))
    {
        // إن كان فيه سيتم تنفيذ أمر الطباعة التالي
        cout << "Element with key '4' is exist and it's value = " << myMap.at(4);
    }
    else
    {
        // إن لم يكن فيه سيتم تنفيذ أمر الطباعة التالي
        cout << "There is no element with key = 4";
    }
    
    return 0;
}

سنحصل على النتيجة التالية عند التشغيل.

Element with key '4' is exist and it's value = Four


في المثال التالي قمنا بتعريف كائن من map مع تحديد أن عناصره تتكون من مفاتيح نوعها int قيم و نوعها string.
بعدها قمنا بحذف عنصر منه بالإعتماد على قيمة مفتاحه و من ثم طباعة قيم جميع العناصر المتبقية بواسطة حلقة.

ملاحظة: قمنا باستخدام الدالة erase() لحذف العنصر.

المثال الخامس

main.cpp
#include <iostream>
#include <map>

using namespace std;

int main()
{
    // string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها map هنا قمنا بتعريف كائن من الكلاس
    map<int, string> myMap = {
        {1, "One"},
        {2, "Two"},
        {3, "Three"},
        {4, "Four"},
        {5, "Five"}
    };
    
    // myMap هنا قمنا بحذف العنصر الذي يملك مفتاح يساوي 3 في الكائن
    myMap.erase(3);

    // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه myMap هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن
    for (auto it = myMap.begin(); it != myMap.end(); ++it)
    {
        // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية
        // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية
        cout << it->first << " - " << it->second << "\n";
    }
    
    return 0;
}

سنحصل على النتيجة التالية عند التشغيل.

1 - One
2 - Two
4 - Four
5 - Five


في المثال التالي قمنا بتعريف كائن من map مع تحديد أن عناصره تتكون من مفاتيح نوعها int قيم و نوعها string.
بعدها قمنا بالبحث عن عنصر يملك مفتاح محدد فيه و في حال وجوده سيتم حذف العنصر من الكائن.
في الأخير قمنا بطباعة قيم جميع العناصر المتبقية بواسطة حلقة.

ملاحظة: قمنا باستخدام الدالة find() للبحث عن العنصر الذي يملك المفتاح في الكائن و الدالة erase() لحذف العنصر من الكائن.

المثال السادس

main.cpp
#include <iostream>
#include <map>

using namespace std;

int main()
{
    // string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها map هنا قمنا بتعريف كائن من الكلاس
    map<int, string> myMap = {
        {1, "One"},
        {2, "Two"},
        {3, "Three"},
        {4, "Four"},
        {5, "Five"}
    };

    // لتخزين مكان العنصر الذي نجد القيمة التي نبحث عنها فيه map<int, string>::iterator منا قمنا بتعريف كائن من 
    map<int, string>::iterator it;

    // it عن عنصر يملك مفتاح يساوي 4, و بالتالي في حال وجود عنصر يملك هذا المفتاح سيتم تخزين عنوانه في الكائن myMap هنا قمنا بالبحث في الكائن
    // فيه للإشارة إلى أنه لم يتم إيجاد أي عنصر يملك هذا المفتاح myMap.end() في حال عدم وجود عنصر يملك مفتاح يساوي 4 سيتم تخزين القيمة التي ترجعها
    it = myMap.find(4);

    // فهذا يعني أنه تم إيجاد العنصر و بالتالي سيتم تنفيذ الكود الموضوع بالداخل myMap.end() لا تساوي القيمة التي ترجعها الدالة it في حال كانت قيمة
    if (it != myMap.end())
    {
        // و من ثم قمنا بحذفه myMap هنا قمنا بطباعة مفتاح العنصر الذي تم إيجاده في الكائن
        cout << "Element with key '"<< it->first << "' is removed from myMap\n\n";
        myMap.erase(it);
    }

    cout << "myMap keys and values:\n";

    // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه myMap هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن
    for (auto it = myMap.begin(); it != myMap.end(); ++it)
    {
        // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية
        // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية
        cout << it->first << " - " << it->second << "\n";
    }
    
    return 0;
}

سنحصل على النتيجة التالية عند التشغيل.

Element with key '4' is removed from myMap

myMap keys and values:
1 - One
2 - Two
3 - Three
5 - Five


في المثال التالي قمنا بتعريف كائنين من map مع تحديد أن عناصرهما تتكون من مفاتيح نوعها int قيم و نوعها string.
بعدها قمنا بتبديل عناصرهما و من ثم طباعة قيم عناصرهما بواسطة حلقة للتأكد من أن التبديل قد تم بنجاح.

ملاحظة: قمنا باستخدام الدالة swap() لتبديل عناصرهما.

المثال السابع

main.cpp
#include <iostream>
#include <map>

using namespace std;

int main()
{
    // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها map هنا قمنا بتعريف كائن من الكلاس
    map<int, string> map1 = {
        {1, "One"},
        {2, "Two"},
        {3, "Three"},
        {4, "Four"}
    };
    
    // بالإضافة إلى أننا قمنا بإضافة عدة قيم فيه string و قيم نوعها int يمكنه أن يحتوي على مفاتيح نوعها map هنا قمنا بتعريف كائن آخر من الكلاس
    map<int, string> map2 = {
        {5, "Five"},
        {6, "Six"},
        {7, "Seven"},
        {8, "Eight"}
    };

    // map2 مع قيم الكائن map1 هنا قمنا بتبديل قيم الكائن
    map1.swap(map2);
    
    cout << "map1 keys and values:\n";

    // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه map1 هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن
    for (auto it = map1.begin(); it != map1.end(); ++it)
    {
        // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية
        // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية
        cout << it->first << " - " << it->second << "\n";
    }
    
    cout << "\nmap2 keys and values:\n";

    // إبتداءاً من أول عنصر وصولاً لآخر عنصر فيه map2 هنا قمنا بإنشاء حلقة تقوم في كل دورة بطباعة قيم عنصر جديد من العناصر الموجودة في الكائن
    for (auto it = map2.begin(); it != map2.end(); ++it)
    {
        // تمثل قيمة العمود الأول في العنصر و التي تعتبر المفتاح الخاص به first الخاصية
        // تمثل قيمة العمود الثاني في العنصر و التي تمثل قيمته second و الخاصية
        cout << it->first << " - " << it->second << "\n";
    }

    return 0;
}

سنحصل على النتيجة التالية عند التشغيل.

map1 keys and values:
5 - Five
6 - Six
7 - Seven
8 - Eight

map2 keys and values:
1 - One
2 - Two
3 - Three
4 - Four