الأربعاء، 22 أكتوبر، 2014

C# - Dictionary

C# - Dictionary
Dictionary(TKey, TValue)
يمثل الـ dictionary مجموعة من المفاتيح Keys والقيم Values .

لاستخدام الـ dictionary نستدعي namespace
using System.Collections.Generic;
مثال,
using System;
using System.Collections.Generic;

namespace ConsoleApplication
{
    class Program
    {
        public class Employee
        {
            public int EmployeeID { get; set; }
            public string Name { get; set; }
            public string Gender { get; set; }
            public double Salary { get; set; }
        }

        static void Main(string[] args)
        {
            // EmployeeID = 1,
            Employee emp1 = new Employee
            {
                EmployeeID = 1,
                Name = "Ali",
                Gender = "Male",
                Salary = 400
            };

            Employee emp2 = new Employee
            {
                EmployeeID = 2,
                Name = "Yasser",
                Gender = "Male",
                Salary = 322
            };

            Employee emp3 = new Employee
            {
                EmployeeID = 3,
                Name = "Sara",
                Gender = "Female",
                Salary = 333
            };

            Dictionary<int, Employee> dictionary = new Dictionary<int, Employee>();
            dictionary.Add(emp1.EmployeeID, emp1);
            dictionary.Add(emp2.EmployeeID, emp2);
            dictionary.Add(emp3.EmployeeID, emp3);

            Employee empIndex = dictionary[1];
            Console.WriteLine("EmployeeID = {0}, Name = {1}, Gender = {2}, Salary = {3})", empIndex.EmployeeID, empIndex.Name, empIndex.Gender, empIndex.Salary);
        }

     
    }
}

النتيجة:

في المثال السابق قمت بإنشاء class باسم Employee وبداخلة أربع خصائص Properties رقم الموظف, الاسم, النوع, الراتب.

ثم داخل الـ Main Method قمت بتعريف ثلاث موظفين باخذ نسخة instance من Employee class

Employee emp1 = new Employee
Employee emp2 = new Employee
Employee emp3 = new Employee
وإضافة البيانات لكل خاصية من الخصائص مثل رقم الموظف والاسم وهكذا.
هنا تم تعريف dictionary

Dictionary<int, Employee> dictionary = new Dictionary<int, Employee>();

ولتعريف الـ dictionary لابد من تحديد أمرين الأول Key والثاني Value, وهنا تم تعريف الـ Key من نوع int والقيمة Value من النوع Employee.

تعريف الKey  من النوع int ليس الزامي ولكن يمكن تعريف اي نوع حسب الحالة التي تعمل عليها وهنا النوع int هو رقم الموظف. وايضا النوع Value تم تعريفة من النوع Employee ولكن يمكن تعريف باي نوع وليكن string او int او double كما تشاء.

تم إدراج الثلاث موظفين داخل ال dictionary list باستخدام Add Method كالتالي:

dictionary.Add(emp1.EmployeeID, emp1);
dictionary.Add(emp2.EmployeeID, emp2);
dictionary.Add(emp3.EmployeeID, emp3);

الـ Add Method تأخد قيمتين من نفس النوع المعرف داخل الـ dictionary list  السابقة.



الـ int key تم اسناد emp1.EmployeeID رقم الموظف ورقم الموظف من النوع int, وEmployee value تم اسناد الـ instance من Employee class.

بعد ذلك تم تحديد موظف محدد لنقوم بطباعة أو إظهار الـ value له وهو رقم 1كالتالي:
Employee empIndex = dictionary[1];

لطباعة بيانات الموظف المحدد رقم 1

Console.WriteLine("EmployeeID = {0}, Name = {1}, Gender = {2}, Salary = {3})", empIndex.EmployeeID, empIndex.Name, empIndex.Gender, empIndex.Salary);

استخدام foreach لطباعة كل الــ Keys:

using System;
using System.Collections.Generic;

namespace ConsoleApplication
{
    class Program
    {
        public class Employee
        {
            public int EmployeeID { get; set; }
            public string Name { get; set; }
            public string Gender { get; set; }
            public double Salary { get; set; }
        }

        static void Main(string[] args)
        {
            // EmployeeID = 1,
            Employee emp1 = new Employee
            {
                EmployeeID = 1,
                Name = "Ali",
                Gender = "Male",
                Salary = 400
            };

            Employee emp2 = new Employee
            {
                EmployeeID = 2,
                Name = "Yasser",
                Gender = "Male",
                Salary = 322
            };

            Employee emp3 = new Employee
            {
                EmployeeID = 3,
                Name = "Sara",
                Gender = "Female",
                Salary = 333
            };

            Dictionary<int, Employee> dic = new Dictionary<int, Employee>();
            dic.Add(emp1.EmployeeID, emp1);
            dic.Add(emp2.EmployeeID, emp2);
            dic.Add(emp3.EmployeeID, emp3);

            foreach (KeyValuePair<int, Employee> item in dic)
            {
                Console.WriteLine("EmployeeID = {0}", item.Key);
            }
        }


    }
}
النتيجة:

باستخدام KeyValuePair مقروء بشكل افضل من استخدام var  وذلك لانه يظهر الـ  Data Type الذي يحتاج إليها.

مثال,

استخدام foreach لطباعة قيم محددة الــ Values:

using System;
using System.Collections.Generic;

namespace ConsoleApplication
{
    class Program
    {
        public class Employee
        {
            public int EmployeeID { get; set; }
            public string Name { get; set; }
            public string Gender { get; set; }
            public double Salary { get; set; }
        }

        static void Main(string[] args)
        {
            // EmployeeID = 1,
            Employee emp1 = new Employee
            {
                EmployeeID = 1,
                Name = "Ali",
                Gender = "Male",
                Salary = 400
            };

            Employee emp2 = new Employee
            {
                EmployeeID = 2,
                Name = "Yasser",
                Gender = "Male",
                Salary = 322
            };

            Employee emp3 = new Employee
            {
                EmployeeID = 3,
                Name = "Sara",
                Gender = "Female",
                Salary = 333
            };

            Dictionary<int, Employee> dic = new Dictionary<int, Employee>();
            dic.Add(emp1.EmployeeID, emp1);
            dic.Add(emp2.EmployeeID, emp2);
            dic.Add(emp3.EmployeeID, emp3);

            foreach (KeyValuePair<int, Employee> item in dic)
            {
                Console.WriteLine("Name = {0}           Salary = {1}", item.Value.Name, item.Value.Salary);
            }
        }
    }
}

النتيجة:


مثال,

استخدام foreach var
using System;
using System.Collections.Generic;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            Dictionary<string, int> dic = new Dictionary<string, int>();
           
            Console.Write("Enter valid integer");
            int amount = int.Parse(Console.ReadLine());

            for (int i = 0; i < amount; i++)
            {
                Console.WriteLine("Enter Name");
                string name = Console.ReadLine();

                Console.WriteLine("Enter Age");
                int age = int.Parse(Console.ReadLine());

                dic.Add(name, age);
            }

            foreach (var item in dic)
            {
                Console.WriteLine("Name is {0} , Age is {1}", item.Key,item.Value);   
            }
        }
    }
}
النتيجة:


ماذا يحث إذا قمنا بإضافة نفس الـ Key ؟
       static void Main(string[] args)
        {
            // EmployeeID = 1,
            Employee emp1 = new Employee
            {
                EmployeeID = 1,
                Name = "Ali",
                Salary = 400
            };

            Employee emp2 = new Employee
            {
                EmployeeID = 2,
                Name = "Yasser",
                Salary = 322
            };

            Dictionary<int, Employee> dic = new Dictionary<int, Employee>();
            dic.Add(emp1.EmployeeID, emp1);
            dic.Add(emp2.EmployeeID, emp2);
           
            // Error Here
            dic.Add(emp2.EmployeeID, emp2);

            foreach (KeyValuePair<int, Employee> item in dic)
            {
                Console.WriteLine("Name = {0}     Salary = {1}", item.Value.Name, item.Value.Salary);
            }
        }
هنا تم إضافة Key مكرر للموظف رقم 2, فحدث خطأ Exception.

Unhandled Exception: System.ArgumentException: An item with the same key has alr
eady been added.

لذلك يجب ان نعلم ان الـ Key هو فريد  uniqueولا يتكرر. ولتفادي هذا الخطأ يجب التأكد من عدم وجود هذا الـ Key. وهنا سوف نستخدم الإجراء ContainsKey Method .


  static void Main(string[] args)
        {
            // EmployeeID = 1,
            Employee emp1 = new Employee
            {
                EmployeeID = 1,
                Name = "Ali",
                Salary = 400
            };

            Employee emp2 = new Employee
            {
                EmployeeID = 2,
                Name = "Yasser",
                Salary = 322
            };

            Dictionary<int, Employee> dic = new Dictionary<int, Employee>();
            dic.Add(emp1.EmployeeID, emp1);
            dic.Add(emp2.EmployeeID, emp2);

            // Check ContainsKey
            if (!(dic.ContainsKey(emp2.EmployeeID)))
            {
                dic.Add(emp2.EmployeeID, emp2);
            }

            foreach (KeyValuePair<int, Employee> item in dic)
            {
                Console.WriteLine("Name = {0} Salary = {1}", item.Value.Name, item.Value.Salary);
            }
        }

ماذا يحدث إذا تم البحث عن Key غير موجود؟

في المثال التالي تم البحث Key بالرقم 777 وهو غير مسجل لدينا داخل ال dictionary list.

using System;
using System.Collections.Generic;

namespace ConsoleApplication
{
    class Program
    {
        public class Employee
        {
            public int EmployeeID { get; set; }
            public string Name { get; set; }
            public double Salary { get; set; }
        }

        static void Main(string[] args)
        {
            // EmployeeID = 1,
            Employee emp1 = new Employee
            {
                EmployeeID = 1,
                Name = "Ali",
                Salary = 400
            };

            Dictionary<int, Employee> dic = new Dictionary<int, Employee>();
            dic.Add(emp1.EmployeeID, emp1);

            // Error Here
            Employee emp = dic[777];
            Console.WriteLine("ID = {0}", emp.EmployeeID);
        }
    }
}

سوف يحدث خطأ وقت التشغيل Run time:

Unhandled Exception: System.Collections.Generic.KeyNotFoundException: The given
key was not present in the dictionary.

ولتفادي هذا الخطأ يجب التأكد من وجود هذا الـ Key. وهنا سوف نستخدم الإجراء ContainsKey Method.


static void Main(string[] args)
        {
            // EmployeeID = 1,
            Employee emp1 = new Employee
            {
                EmployeeID = 1,
                Name = "Ali",
                Salary = 400
            };

            Dictionary<int, Employee> dic = new Dictionary<int, Employee>();
            dic.Add(emp1.EmployeeID, emp1);

            // Check Here
            if (dic.ContainsKey(777))
            {
                Employee emp = dic[777];
                Console.WriteLine("ID = {0}", emp.EmployeeID);
            }
            else
            {
                Console.WriteLine("EmployeeID not found!");
            }

        }



استخدام الإجراء TryGetValue Method

الهدف من استخدام TryGetValue Method هو التأكد من وجود Key معين دون ظهور خطأ Exception.

using System;
using System.Collections.Generic;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            Student stu1 = new Student() { ID = 1, Name = "Ahmed", Gender = "Male", Degree = 8 };
            Student stu2 = new Student() { ID = 2, Name = "Taha", Gender = "Male", Degree = 9.1 };

            Student stu3 = new Student();
            stu3.ID = 3;
            stu3.Name = "Sara";
            stu3.Gender = "Female";
            stu3.Degree = 7.3 ;
           
            Dictionary<int, Student> Dic = new Dictionary<int, Student>();
            Dic.Add(stu1.ID, stu1);
            Dic.Add(stu2.ID, stu2);
            Dic.Add(stu3.ID, stu3);

            Student st;

            if(Dic.TryGetValue(5,out st))
            {
                Console.WriteLine("ID= {0} Name= {1} Degree= {2}", st.ID,st.Name,st.Degree);
            }
            else
            {
                Console.WriteLine("The key is not found!");
            }
        }
        public class Student
        {
            public int ID { get; set; }
            public string Name { get; set; }
            public string Gender { get; set; }
            public double Degree { get; set; }
        }
    }
}


في هذا المثال تم تعريف Student class وتم إدراج اربع خصائص Properties به وهي رقم ID, و الاسم و النوع والدرجة.
بعد ذلك داخل الـ Main Method تم تعريف ثلاث نسخ instance من Student class وهماstu1, stu2, stu3  و تم تعريف قيم للـ Properties

{ ID = 1, Name = "Ahmed", Gender = "Male", Degree = 8 };
{ ID = 2, Name = "Taha", Gender = "Male", Degree = 9.1 };

Student stu3 = new Student();
            stu3.ID = 3;
            stu3.Name = "Sara";
            stu3.Gender = "Female";
            stu3.Degree = 7.3 ;

بعد ذلك استخدمنا if(Dic.TryGetValue(5,out st)) وهو للتحقق من الـ Key دون حدوث خطأ.

النتيجة:

لم يتم العثور علي المفتاح Key ولم يحدث خطأ Exception ولكن فقط ظهرت رسال.




استخدام Count

لمعرفة عدد عناصر الـ dictionary نستخدمة الخاصية Count Property أو استخدام الإجراء Count Method ولكن في هذه الحالة سوف نستدعي namespace using System.Linq لنتمكن من استخدام Count Method.

مثال,


using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            Student stu1 = new Student() { ID = 1, Name = "Ahmed", Gender = "Male", Degree = 8 };
            Student stu2 = new Student() { ID = 2, Name = "Taha", Gender = "Male", Degree = 9.1 };
            Student stu3 = new Student() { ID = 3, Name = "Sara", Gender = "Female", Degree = 7.3 };

            Dictionary<int, Student> Dic = new Dictionary<int, Student>();
            Dic.Add(stu1.ID, stu1);
            Dic.Add(stu2.ID, stu2);
            Dic.Add(stu3.ID, stu3);

            Console.WriteLine("Total Count Property= {0}", Dic.Count);
            Console.WriteLine("Total Count Method = {0}", Dic.Count());
        }
        public class Student
        {
            public int ID { get; set; }
            public string Name { get; set; }
            public string Gender { get; set; }
            public double Degree { get; set; }
        }
    }

}



النتيجة:


مثال آخر علي استخدام الإجراء Count Method عن طريق Lambda Expression.


using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            Student stu1 = new Student() { ID = 1, Name = "Ahmed", Gender = "Male", Degree = 8 };
            Student stu2 = new Student() { ID = 2, Name = "Taha", Gender = "Male", Degree = 9.1 };
            Student stu3 = new Student() { ID = 3, Name = "Sara", Gender = "Female", Degree = 7.3 };

            Dictionary<int, Student> Dic = new Dictionary<int, Student>();
            Dic.Add(stu1.ID, stu1);
            Dic.Add(stu2.ID, stu2);
            Dic.Add(stu3.ID, stu3);
           
            //Using Lambda Expressions
            Console.WriteLine("Total Count Method = {0}", Dic.Count(kvp => kvp.Value.Degree > 7));
        }
        public class Student
        {
            public int ID { get; set; }
            public string Name { get; set; }
            public string Gender { get; set; }
            public double Degree { get; set; }
        }
    }
}

هنا نريد معرفة عدد Count الطلبه التي درجاتهم أكبر من 7.5

النتيجة: