المصفوفات والحلقة التكرارية foreach في C#

تستخدم المصفوفات أو بما تعرف ب array في جميع لغات البرمجة و تعتبر عنصرا لا يستغني عنه المبرمج, حيث تسهل المصفوفات عملية تخزين البيانات والوصول إليها بطريقة سريعة.
تتم عملية تخزين المتغيرات في المصفوفات على شكل جداول.
وكل متغير له رقمه الخاص في الجدول index حيث يتم الوصول إلى هذا المتغير في الجدول عن طريق رقمه مباشرة.
طريقة كتابة وتعريف المصفوفات arrays.
الطريقة الأولى: مصفوفات محددة الحجم.
هذه الطريقة تلزمنا بتحديد عدد العناصر في المصفوفة قبل تعبئتها, وذلك كما يلي:
int[] x = new int[10];  // مصفوفة تحتوي على 10 متغيرات من نوع أرقام فقط
string[] name = new string[5]; // مصفوفة تحتوي على 5 متغيرات من نوع نصي
كما لاحظنا في المثال أعلاه, تم تحديد عدد العناصر في كل من المصفوفتين قبل إنشائهما, وهذا له الكثير من الفوائد من بينها إمكانية تحديد رقم العناصر بالشكل الذي نريده في الجدول, كما هو مبين في المثال التالي:
name[0] = "mohamad";   // ضبط الاسم كقيمة للخانة الأولى في المصفوفة
name[1] = "ahmed";    //إضافة إسم آخر الى الخانة الثانية في المصفوفة
ملاحظة:  الحساب في المصفوفة يبدأ من الخانة 0 أي أن الخانة name[0] هي الأولى و الخانة name[1] هي الثانية.
إضافة إلى ذلك, في المثالين السابقين تم الإعلان عن المصفوفتين بدون تعبئتهما بأي قيم, وهذا ما يمكن اختصاره بإنشاء مصفوفات محددة الحجم وتعبئتها في نفس الوقت.
دعونا نعيد كتابة المثالين السابقين مع تعبئة المصفوفتين بالقيم:
int[] x = new int[10] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };  // مصفوفة تحتوي على 10 متغيرات من نوع أرقام فقط من 0 إلى 9
string[] name = new string[5] { "Mohamad", "Ali", "Sara", "Anas", "Ahmad"}; // مصفوفة تحتوي على 5 قيم من نوع نصي فقط
الطريقة الثانية: مصفوفات غير محددة الحجم.
هذه الطريقة هي الأكثر شيوعا وذلك نظرا لسهولتها, لأنها تلزمنا بتحديد عدد العناصر في المصفوفة قبل تعبئتها, وذلك كما يلي:
int[] x = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };  // مصفوفة تحتوي على متغيرات من نوع أرقام فقط ولكن دون تحديد حجمها
string[] name = { "Mohamad", "Bashir", "Hassiba", "Anas", "Sulaiman"}; // مصفوفة تحتوي على قيم من نوع نصي فقط ولكن دون تحديد حجمها
double[] myDouble = {1.9, 2.9, 3.4, 3.5};
bool[] myBoolean = {true,false,false};
char[] myChar = {‘A’,’b’,’@’,’C’};
كيفية طباعة العناصر في المصفوفات
يمكن طباعة عناصر محددة أو كل العناصر من المصفوفات باستخدام عدة طرق, أهمها طباعة العناصر من خلال الفهرس الخاص بها في المصفوفة, وكذلك طباعة العناصر من خلال الحلقات التكرارية وهي: for, while, و foreach.
طباعة العناصر من خلال الفهرس الخاص بها
لنلاحظ المثال التالي:
string[] name = { "Mohamad", "Ali", "Sara", "Anas", "Ahmad"};
Console.WriteLine(name[0]); // المخرج هو Mohamad
Console.WriteLine(name[1]); // المخرج هو Ali
Console.WriteLine(name[2]); // المخرج هو Sara
Console.WriteLine(name[3]); // المخرج هو Anas
Console.WriteLine(name[4]); // المخرج هو Ahmad
كما نلاحظ هذه الطريقة سريعة ومفيدة جدا خصوصا في عمليات الطباعة التي لا تعتمد على التكرار والتي لا تتبع نمطا محددا لعرض البيانات.
طباعة العناصر من خلال الحلقات التكرارية
الطباعة باستخدام حلقة for
لنطبق ما تعلمناه في الدروس السابقة حول حلقة for في المثال التالي:
int[] x = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
for (int i = 0; i < 10; i++)
{
  Console.WriteLine(x[i]);
}
// الناتج
//0
//1
//2
//3
//4
//5
//6
//7
//8
//9
الطباعة باستخدام حلقة while
وفي المثال الآتي تذكير بحلقة while:
int[] x = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int i=0;
while (i<10)
 {
    Console.WriteLine(x[i]);
    i++;
 }
// الناتج هو نفس الناتج في المثال السابق مع حلقة for
ما نستنتجه من المثالين السابقين هو أن متغير الحلقة i يعتبر بمثابة نائب عن كل العناصر الموجودة في المصفوفة, وكل ما تغيرت قيمته يتغير العنصر الذي نطبعه من المصفوفة, ففهنا مثلا يبدأ من القيمة 0 ثم تزداد قيمته بواحد في كل مرة, إلى أن تصبح قيمته تساوي 11, وبالتالي يصبح الشرط i<10 خاطئا وتتوقف الحلقة عن الدوران بعد أن مرت على كل العناصر.
الطباعة باستخدام حلقة foreach
الحلقة التكرارية foreach شبيهة بالحلقة التكرارية for, أي أنها تمكننا من المرور على كل العناصر وكذا تنفيذ مختلف العمليات عليها.
ما يميز الحلقة التكرارية foreach هو أنها توفر لنا طريقة أبسط لتكرار العمليات, فيكفي أن نحدد متغير الحلقة ونربطه بالمصفوفة التي سيمر عليها وستتم الطباعة دون تحديد شرط لإيقاف الحلقة عن الدوران.
في المثال التالي سنستخدم حلقة foreach لطباعة كل العناصر الموجودة في المصفوفة.
int[] x = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
foreach (int item in x)
{
  Console.WriteLine(item);
}
// الناتج هو نفس الناتج في المثال السابق مع حلقتي for و while
مثال آخر على السلاسل النصية:
string[] name = { "Mohamad", "Ali", "Sara", "Anas", "Ahmad"};
foreach (string item in name)
{
  Console.WriteLine(item);
}
// الناتج
// Mohamad
// Ali
// Sara
//Anas
//Ahmad
أهم الخصائص والعمليات في المصفوفات Arrays
الخصائص
معرفة طول المصفوفة من خلال خاصية Length
لعل أهم خاصية في المصفوفات هي Length, وهذه الخاصية تساعدنا على معرفة طول المصفوفة, أي عدد العناصر الموجودة فيها.
مثال:
int[] x = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Console.WriteLine(x.Length); // الناتج هو 10 لأن عدد العناصر في المصفوفة هو 10.
string[] name = { "Mohamad", "Ali", "Sara", "Anas", "Ahmad"};
Console.WriteLine(name.Length); // الناتج هو 5 لأن عدد العناصر في المصفوفة هو 5.
أهم العمليات
ترتيب المصفوفات
يتم ترتيب عناصر المصفوفات رقميا أو أبجديا من الأصغر إلى الأكبر حسب نوع المصفوفة كما هو مبين في الأمثلة التالية:
ترتيب مصفوفة من نوع رقمي
int[] x = { 10, 1, 3, 6, 4, 27, 18, 2 };
Array.Sort(x);
foreach (int i in x)
{
  Console.WriteLine(i);
}
// الناتج
//1
//2
//3
//4
//6
//10
//18
//27
ترتيب مصفوفة من نوع نصي
string[] name = { "Mohamad", "Ali", "Sara", "Anas", "Ahmad"};
Array.Sort(name);
foreach (string i in name)
{
  Console.WriteLine(i);
}
// الناتج
//Ahmad
//Ali
//Anas
//Mohamad
//Sara
قلب المصفوفات
قلب المصفوفات مشابه لحد كبير لترتيب المصفوفات ونستخدم فيه Array.Reverse.
نشير هنا إلى أن عملية قلب المصفوفات تتم بدون ترتيب العناصر.
قلب مصفوفة من نوع رقمي
int[] x = { 10, 1, 3, 6, 4, 27, 18, 2 };
Array.Reverse(x);
foreach (int i in x)
{
  Console.WriteLine(i);
}
// الناتج
//2
//18
//27
//4
//6
//3
//1
//10
قلب مصفوفة من نوع نصي
string[] name = { "Mohamad", "Ali", "Sara", "Anas", "Ahmad"};
Array.Reverse(name);
foreach (string i in name)
{
  Console.WriteLine(i);
}
// الناتج
//Ahmad
//Anas
//Sara
//Ali
//Mohamad
عمليات max, min, و sum
ملاحظة هامة: لاستخدام هذه العمليات يرجى إضافة مجال الأسماء System.Linq في بداية البرنامج كما سنرى في الأمثلة.
Max
تقوم هذه الدالة بإرجاع أكبر عنصر في المصفوفة.
مثال:
using System;
using System.Linq;
namespace Example
{
  class Program
  {
    static void Main(string[] args)
    {
        int[] x = { 10, 1, 3, 6, 4, 27, 18, 2 };
        Console.WriteLine(x.Max());
    }
  }
}
// الناتج
// 27
Min
على العكس من Max, تقوم دالة Min بإرجاع أصغر عنصر في المصفوفة.
مثال:
using System;
using System.Linq;
namespace Example
{
  class Program
  {
    static void Main(string[] args)
    {
        int[] x = { 10, 1, 3, 6, 4, 27, 18, 2 };
        Console.WriteLine(x.Min());
    }
  }
}
// الناتج
// 1
Sum
تقوم هذه الدالة بإرجاع مجموع عناصر المصفوفة.
ملاحظة: يشترط مع هذه العملية أن تكون العناصر قابلة للجمع, أي أن تكون أعدادا رقمية أو عشرية.
مثال:
using System;
using System.Linq;
namespace Example
{
  class Program
  {
    static void Main(string[] args)
    {
        int[] x = { 10, 1, 3, 6, 4, 27, 18, 2 };
        Console.WriteLine(x.Sum());
    }
  }
}
// الناتج
// 71
خلاصة
تعتبر المصفوفات من أنواع البيانات البالغة الأهمية في لغة C#, إلا أن إجراء بعض العمليات عليها كالبحث والفلترة صعب بعض الشيء, وسنخصص لهذه العمليات درسا خاصا خلال هذه الدورة.
كما أن المصفوفات لا تدعم الكثير من العمليات المهمة كدوال الإضافة والمسح, وهذا ما سنتطرق له في الدرس القادم والذي سيكون مخصصا للقوائم Lists.