مسائل حول الأراي واستخدام الـ Loops
السلام عليكم ورحمة الله وبركاته
الفهرس
المقدمة
الأراي كما شرحناها سابقًا هي نوع من أنواع هياكل البيانات التي تستخدم لتخزين مجموعة من القيم والبيانات المرتبطة ببعضها تحت مسمى واحد
int arr[5] = {1, 2, 3, 4, 5};
// arr[0] = 1
// arr[1] = 2
// arr[2] = 3
// arr[3] = 4
// arr[4] = 5
والأراي تعد من أهم الأمور التي ستستخدمها في مسيرتك البرمجية وستساعدك في حل العديد من المشكلات والمسائل البرمجية
على سبيل المثال معك أراي تحتوي عن مجموعة من الأرقام، أريدك أن:
- ايجاد أكبر عنصر في الأراي
- ايجاد أصغر عنصر في الأراي
- حساب مجموع عناصر الأراي
- البحث في الأراي عن عنصر معين
- طباعة عناصر الأراي المتكررة
- ترتيب عناصر الأراي بشكل تصاعدي أو تنازلي
- ... إلخ
ولكل هذه المسائل سنقوم بحلها في هذا الدرس وسنتعرف على كيفية استخدام الـ Loops
لحل هذه المسائل
في الحقيقة استخدام الـ Loops
مع الأراي أمر شائع ومن أهم الأمور التي يجب أن تنقنها
لأنك في كل مرة تريد القيام بعملية معينة في الأراي ستحتاج إلى الـ Loops
طباعة عناصر الأراي باستخدام الـ Loop
لنفترض أن لدينا أراي تحتوي على مجموعة من الأرقام العشوائية بهذا الشكل
int arr[10] = {12, 45, 7, -23, 59, 0, -300, 67, -1, 5};
وقلت لك ببساطة أن تطبع لي جميع العناصر في الأراي
ما كنا نقوم به هو أن نستخدم الـ index
للوصول إلى كل عنصر في الأراي ونطبعه
cout << arr[0] << '\n'; // 12
cout << arr[1] << '\n'; // 45
cout << arr[2] << '\n'; // 7
cout << arr[3] << '\n'; // 23
cout << arr[4] << '\n'; // -9
// ... etc.
لكن هذا ليس حل جيد كما تلاحظ لأنه إذا كانت الأراي تحتوي على عدد كبير من العناصر مثلًا 100
فإن الأمر سيكون متعبًا ومكررًا
لذلك نستخدم الـ Loop
هنا لتساعدنا على المرور على كل عناصر الأراي
أنت كل ما تحتاجه هو أن تجعل الـ index
يتغير من 0
إلى n-1
حيث n
هو عدد العناصر في الأراي
int arr[10] = {12, 45, 7, -23, 59, 0, -300, 67, -1, 5};
int i = 0;
while (i < 10) {
cout << arr[i] << '\n';
i++;
}
هنا قمنا بإنشاء متغير i
ليمثل لنا الـ index
وبدأنا من 0
ثم في كل مرة نقوم بطباعة العنصر arr[i]
ونزيد قيمة i
بواحد عن طريق i++
هكذا في كل لفة سيتم طباعة عنصر من الأراي بالترتيب حتى نصل إلى نهاية الأراي
لأن الـ i
يبدأ من 0
ثم نطبع arr[0]
ثم نزيد i
ليصبح 1
ثم نطبع arr[1]
وهكذا حتى نصل إلى أخر index
وهو الشرط i < 10
الذي يوقف الـ while
هنا استخدمنا الـ while
للقيام بذلك ولكن يمكنك استخدام الـ for
أيضًا
وهذا هو الكود بالـ for
int arr[10] = {12, 45, 7, -23, 59, 0, -300, 67, -1, 5};
for (int i = 0; i < 10; i++) {
cout << arr[i] << '\n';
}
طباعة عناصر الأراي بشكل عكسي
إذا أردنا طباعة الأراي بشكل عكسي بمعنى أن نبدأ من العنصر الأخير وننتهي بالعنصر الأول
يمكننا استخدام الـ loop
بنفس الطريقة لكن نجعل المتغير i
الذي يمثل index
يبدأ من الـ index
الخاص بالعنصر الأخير في الأراي وننقصه بدلًا من زيادته حتى يصل إلى 0
int arr[10] = {12, 45, 7, -23, 59, 0, -300, 67, -1, 5};
int i = 9;
while (i >= 0) {
cout << arr[i] << '\n';
i--;
}
لاحظ أننا هنا بدأنا من 9
لأن أخر index
في الأراي الذي يحتوي على 10
عناصر هو 9
وليس كما تعرف
ثم لاحظ أن الشرط هنا هو i >= 0
وهذا يعني أن الـ loop
ستستمر طالما i
أكبر من أو تساوي الـ 0
وبالطبع ننقص i
في كل لفة بواحد حتى نصل إلى 0
هكذا في أول لفة قيمة i
ستكون 9
ثم سنطبع arr[9]
ثم ننقص قيمة i
الآن في اللفة الثانية قيمة i
تساوي 8
لذا سنطبع arr[8]
ثم ننقص قيمة i
ليصبح 7
ونستمر هكذا حتى نصل إلى الـ 0
وننتهي من الـ loop
بالطبع يمكنك استخدام الـ for
بدلًا من الـ while
للقيام بنفس العملية
int arr[10] = {12, 45, 7, -23, 59, 0, -300, 67, -1, 5};
for (int i = 9; i >= 0; i--) {
cout << arr[i] << '\n';
}
طباعة عناصر الأراي بناءً على شرط معين
الآن لنفترض أن الأراي تحتوي على مجموعة من الأرقام العشوائية ونريد طباعة الأرقام السالبة فقط
يمكننا استخدام الـ loop
مع الشرط if
للقيام بذلك
int arr[10] = {12, 45, 7, -23, 59, 0, -300, 67, -1, 5};
for (int i = 0; i < 10; i++) {
if (arr[i] < 0) {
cout << arr[i] << '\n';
}
}
هنا قمنا بإنشاء الـ loop
وفي كل لفة نتحقق من قيمة العنصر arr[i]
إذا كانت أقل من الـ 0
نطبعها
وهكذا سيتم طباعة الأرقام السالبة فقط
بالطبع يمكنك تغير الشرط ليطبع لك الأرقام الموجبة فقط أو الأرقام الزوجية أو الفردية أو الأرقام التي تقبل القسمة على 3
أو أي شرط تريده
يمكنك تجربة ذلك بنفسك والتعديل على الشرط حسب ما تريد
إيجاد أكبر عنصر في الأراي
فكر معي في هذه المسألة، كيف يمكننا إيجاد أكبر عنصر في الأراي ؟
يمكنك المرور على كل عناصر الأراي ويمكنك عمل شرط معين
لكن ما هو هذا الشرط ؟ هل يمكنك تفكير فيه ؟
نحتاج لشرط يقول لنا أن الرقم الذي نحن فيه الآن هو أكبر من الأرقام التي مررنا عليها حتى الآن
بمعنى أننا لدينا أراي بهذا الشكل
int arr[10] = {12, 45, 7, -23, 59, 0, -300, 67, -1, 5};
الآن نحن نستطيع عمل loop
يمر على كل العناصر
في اللفة الأولى نحن نكون عن العنصر 12
وفي اللفة الثانية نكون عن العنصر 45
وفي اللفة الثالثة نكون عن العنصر 7
وهكذا
نحتاج لشيء يخبرنا أن العنصر الذي نحن فيه الآن هو أكبر رقم ممر عليه حتى الآن
بالتالي نحتاج لمتغير يحتفظ بأكبر رقم مررنا عليه حتى الآن ونقارنه بكل عنصر جديد نمر عليه
بالتالي عندما نقف على العنصر 12
في اللفة الأولى نقول أن 12
هو أكبر رقم وجددناه حتى الآن
ثم نمر على العنصر 45
في اللفة الثانية ونقارنه بالـ 12
سنجد أن 45
أكبر من 12
لذا سنقول أن 45
هو أكبر رقم وجددناه لذا سنقوم بتغيير المتغير الذي كان يحتفظ بأكبر رقم ونجعله يحتفظ بـ 45
ثم نمر على العنصر 7
في اللفة الثالثة ونقارنه بالـ 45
سنجد أن 45
يظل أكبر من 7
لذا لن نقوم بتغيير المتغير الذي يحتفظ بأكبر رقم وجدناه
وهكذا حتى نصل إلى نهاية الأراي
لنكتب الكود ثم نقوم بشرحه وتحليله في جدول جميل
int arr[10] = {12, 45, 7, -23, 59, 0, -300, 67, -1, 5};
// ننشئ متغير ليحتفظ بأكبر عنصر ونفترض أن العنصر الأول هو الأكبر
int max_value = arr[0];
// نبدأ من العنصر الثاني لأن الأول افترضنا أنه الأكبر
for (int i = 1; i < 10; i++) {
if (arr[i] > max_value) {
max_value = arr[i];
}
}
أهم جزء هنا هو جزء الـ if
حيث نقوم بالتحقق إذا كان العنصر الذي نحن فيه الآن arr[i]
أكبر من قيمة max_value
إذا كان العنصر الحالي أكبر من max_value
فسنقوم بتحديث قيمة max_value
لتكون العنصر الحالي
وإذا لم يكن العنصر الحالي أكبر من max_value
فلن نقوم بتحديث قيمة max_value
وسنستمر في الـ loop
حتى نصل إلى نهاية الأراي
قيمة i |
قيمة arr[i] |
قيمة max_value |
الشرط arr[i] > max_value |
النتيجة |
---|---|---|---|---|
1 | 45 | 12 | الشرط 45 > 12 سيعطي true |
إذًا قم بتحديث قيمة max_value max_value = 45 |
2 | 7 | 45 | الشرط 7 > 45 سيعطي false |
لن نقوم بتحديث القيمة |
3 | -23 | 45 | الشرط -23 > 45 سيعطي false |
لن نقوم بتحديث القيمة |
4 | 59 | 45 | الشرط 59 > 45 سيعطي true |
إذًا قم بتحديث قيمة max_value max_value = 59 |
5 | 0 | 59 | الشرط 0 > 59 سيعطي false |
لن نقوم بتحديث القيمة |
6 | -300 | 59 | الشرط -300 > 59 سيعطي false |
لن نقوم بتحديث القيمة |
7 | 67 | 59 | الشرط 67 > 59 سيعطي true |
إذًا قم بتحديث قيمة max_value max_value = 67 |
8 | -1 | 67 | الشرط -1 > 67 سيعطي false |
لن نقوم بتحديث القيمة |
9 | 5 | 67 | الشرط 5 > 67 سيعطي false |
لن نقوم بتحديث القيمة |
بهذا الشكل سنحصل على أكبر عنصر في الأراي وهو 67
بالطبع يمكنك استخدام نفس الطريقة لإيجاد أصغر عنصر في الأراي
أو إيجاد أكبر رقم سالب أو أصغر رقم فردي أو أي شيء تريده
هذه أفكار ومسائل يمكنك تطبيقها بنفس الطريقة وستساعدك في فهم كيفية استخدام الـ Loops
مع الأراي بشكل أفضل
وستساعدك في حل العديد من المسائل البرمجية وستوسع أفكارك
حساب مجموع عناصر الأراي
الآن لنفكر في كيفية حساب مجموع عناصر الأراي
أولاً نحتاج لمتغير يحتفظ بالمجموع الكلي تبدأ قيمته بـ 0
ثم نمر على كل عنصر في الأراي وفي كل لفة نجمع قيمة العنصر الذي نقف عليه بالمتغير الذي يحتفظ بالمجموع الكلي
int arr[10] = {12, 45, 7, -23, 59, 0, -300, 67, -1, 5};
// ننشئ متغير ليحتفظ بالمجموع الكلي وبالطبع قيمته ستكون هي 0 لأننا سنجمع عليه
int sum = 0;
// نمر على كل عناصر الأراي وجمع قيمة كل عنصر إلى المتغير بشكل مباشر
for (int i = 0; i < 10; i++) {
sum += arr[i];
}
هنا قمنا بإنشاء متغير sum
ليحتفظ بالمجموع الكلي وبدأنا قيمته بـ 0
ثم نمر على كل عنصر في الأراي وفي كل لفة نقوم بجمع قيمة العنصر arr[i]
بالمتغير sum
الأمر بهذه البساطة حتى أنه أبسط من المسألة السابقة لأننا لا نحتاج لشرط معين هنا فقط نقوم بجمع بشكل مباشر في كل لفة
قيمة i |
قيمة arr[i] |
قيمة sum قبل الإضافة |
قيمة sum بعد الإضافة sum += arr[i] |
---|---|---|---|
0 | 12 | 0 | 12 |
1 | 45 | 12 | 57 |
2 | 7 | 57 | 64 |
3 | -23 | 64 | 41 |
4 | 59 | 41 | 100 |
5 | 0 | 100 | 100 |
6 | -300 | 100 | -200 |
7 | 67 | -200 | -133 |
8 | -1 | -133 | -134 |
9 | 5 | -134 | -129 |
بهذا الشكل سنحصل على مجموع عناصر الأراي وهو -129
البحث عن عنصر معين في الأراي
حسنًا، الآن لنفكر في كيفية البحث عن عنصر معين في الأراي
فكر معي في كيفية البحث عن عنصر معين في الأراي ؟
سنفترض أن العنصر الذي نبحث عنه هو 59
نريد أن نعرف ما إذا كان هذا العنصر موجود في الأراي أم لا
وإذا كان موجودًا نريد أن نعرف موقعه في الأراي، أي الـ index
الذي يتواجد فيه
وإذا لم يكن موجودًا نريد أن تطبع جملة تقول أن العنصر غير موجود
كيف يمكننا القيام بذلك ؟
حسنًا، أولًا سيكون لدينا متغير يدعى target
وهو العنصر الذي نبحث عنه وهو من معطيات المسألة وهو 59
الآن نستطيع المرور على كل عناصر الأراي وفي كل لفة نقوم بالتحقق إذا كان العنصر arr[i]
يساوي target
أم لا
int arr[10] = {12, 45, 7, -23, 59, 0, -300, 67, -1, 5};
// العنصر الذي نبحث عنه
int target = 59;
// نمر على كل عناصر الأراي ونقارن كل عنصر بالعنصر المطلوب
for (int i = 0; i < 10; i++) {
if (arr[i] == target) {
cout << "We found the target, and its index is: " << i << '\n';
break;
}
}
هنا لدينا متغير target
الذي يحتفظ بالعنصر الذي نبحث عنه وهو 59
نحن بكل بساطة نمر على كل عناصر الأراي وفي كل لفة نقارن قيمة الـ arr[i]
بقيمة target
هل قيمة arr[i]
تساوي قيمة target
أم لا ؟
إذا كانت تساوي فسنقوم بطباعة جملة تقول أننا وجدنا العنصر وموقعه في الأراي
وبعد ذلك سنقوم بإيقاف الـ loop
بواسطة الأمر break
لأننا وجدنا العنصر ولا داعي للمتابعة
لاحظ أننا استخدمنا الـ break
لإيقاف الـ loop
بمجرد العثور على العنصر المطلوب
ولو لم نستخدم الـ break
فسيستمر الـ loop
حتى نصل إلى نهاية الأراي برغم من أننا وجدنا العنصر
هنا لدينا مشكلة صغير وهي ماذا لو لم نجد العنصر المطلوب ؟
ألم نقل أننا نريد أن تطبع جملة تقول أن العنصر غير موجود ؟ كيف يمكننا القيام بذلك ؟
نحتاج لشيء يخبرنا أننا مررنا بكل عناصر الأراي ولم نجد العنصر المطلوب
لكي نستخدمه في النهاية ونرى هل وجدنا العنصر أم لا وبناءً عليه نطبع الجملة المناسبة
هنا يمكننا عمل متغير يسمى found
ويكون من نوع bool
بالتالي يمكنه أن يكون true
أو false
لنجعل قيمته الافتراضية false
ونقوم بتغيير قيمته إلى true
إذا وجدنا العنصر المطلوب
int arr[10] = {12, 45, 7, -23, 59, 0, -300, 67, -1, 5};
// العنصر الذي نبحث عنه
int target = 999; // رقم غير موجود في الأراي
// متغير ليخبرنا إذا وجدنا العنصر المطلوب أم لا
bool found = false;
// نمر على كل عناصر الأراي ونقارن كل عنصر بالعنصر المطلوب
for (int i = 0; i < 10; i++) {
if (arr[i] == target) {
cout << "We found the target, and its index is: " << i << '\n';
found = true; // لنعرف أننا وجدنا العنصر true نغير قيمته إلى
break;
}
}
// نتحقق هل وجدنا العنصر أم لا
if (found == false) {
cout << "The target is not found in the array\n";
}
لاحظ أننا هنا قمنا بإنشاء متغير found
من نوع bool
وقيمته الافتراضية هي false
ثم نمر على كل عناصر الأراي وفي كل لفة نقوم بالتحقق إذا كان العنصر arr[i]
يساوي target
إذا تحقق الشرط نقوم بطباعة جملة تقول أننا وجدنا العنصر ونغير قيمة found
إلى true
وإذا لم يتحقق فسنستمر في الـ loop
حتى ننتهي من الأراي وستظل قيمة found
تساوي false
قيمته الافتراضية
ثم في نهاية الـ loop
نتحقق إذا كانت قيمة found
تساوي false
أي أنها ظلت كما هي ولم تتغير إلى true
فهذا يعني أننا لم نجد العنصر المطلوب
لذا سنقوم بطباعة جملة تقول أن العنصر غير موجود في الأراي
for-each loop
حسنًا تعرفنا سابقًا عن الـ for
والـ while
والـ do while
وكيفية استخدامها ورأينا بعض الأمثلة مع الأراي وغيرها
وقلنا أنها تساعدنا في تكرار العمليات والتحكم فيها والقيام بعمليات معينة في كل لفة
وقلنا أن هناك أدوات أخرى تساعدنا في الـ Loops
مثل الـ recursion
والـ for-each loop
وغيرها
الآن سنتعرف على الـ for-each loop
أولًا هي لها العديد من الأسماء والمتشابهات والنسخ مثل الـ for-each loop
والـ for in loop
والـ for of loop
وغيرها الكثير بحسب اللغة
وكل لغة لها طريقتها الخاصة في بناء الـ for-each loop
ولكن الفكرة العامة واحدة
الـ for-each loop
تساعدنا في تكرار العناصر في الأراي بدون الحاجة للتحكم في الـ index
لأنها تقوم بالمرور على الأراي وتعطيك في كل لفة قيمة العنصر مباشرةً بدون الحاجة للـ index
لنرى مثال بسيط على الـ for-each loop
في الـ C++
int arr[10] = {12, 45, 7, -23, 59, 0, -300, 67, -1, 5};
for (int element : arr) {
cout << element << '\n';
}
هنا قمنا بإنشاء الـ for-each loop
وفي كل لفة سيتم إعطائك قيمة العنصر مباشرةً
لاحظ شكلها البسيط والسريع في كتابة كود، وكما تلاحظ نحن فقط ننشيء متغير سيمثل كل عنصر من عناصر الأراي وهو element
ويمكنك بالطبع تسميته كما تشاء
ثم ستقوم الـ loop
كالعادة بالمرو كل عنصر عنصر في كل لفة وتخزين العنصر الي تقف عليه حاليًا في هذا المتغير الذي انشأناه
لو أردنا كتابة نفس الكود بالـ for
العادي سيكون بهذا الشكل
int arr[10] = {12, 45, 7, -23, 59, 0, -300, 67, -1, 5};
for (int i = 0; i < 10; i++) {
cout << arr[i] << '\n';
}
هنا نرى أن الـ for-each loop
تساعدنا في تقليل الكود وتبسيطه وتجعله أكثر وضوحًا وسهولة في القراءة
لكنها كما لاحظت مرتبطة بشكل أساسي بالأراي لذا استخداماتها محصورة في الأراي فقط وما يشابهها (وستعرف ما أقصده لاحقًا)
وهي لا تعطيك الـ index
لذا إذا كنت بحاجة للـ index
فعليك استخدام الـ for
العادي
وبما أن الـ string
يعتبر أراي من الـ char
فيمكننا استخدام الـ for-each
للمرور على كل حرف من حروف الـ string
string name = "Ahmed";
for (char character : name) {
cout << character << '\n';
}
لاحظ هنا أننا جعلنا المتغير الذي سيحتفظ بكل حرف في كل لفة نوعه char
أظنك تعرف السبب ولا داعي للتفسير مجددًا
بالطبع يمكنك استخدام الـ for-each loop
مع الأراي لتنفيذ العديد من الأمور المتعلقة بالأراي
مثل البحث عن عنصر معين أو حساب مجموع العناصر أو إيجاد أكبر عنصر أو غيرها من الأمثلة التي عرضناها سابقًا
تريد مجموع العناصر في الأراي ؟
int arr[10] = {12, 45, 7, -23, 59, 0, -300, 67, -1, 5};
int sum = 0;
for (int element : arr) {
sum += element;
}
cout << "The sum of the elements is: " << sum << '\n';
تريد أكبر عنصر في الأراي ؟
int arr[10] = {12, 45, 7, -23, 59, 0, -300, 67, -1, 5};
int max_value = arr[0];
for (int element : arr) {
if (element > max_value) {
max_value = element;
}
}
cout << "The max value is: " << max_value << '\n';
لاحظ أننا هنا نستخدم الـ for-each loop
بنفس الطريقة التي استخدمناها في الأمثلة السابقة
لكن لاحظ أننا لا نحتاج للـ index
لذا لما نتعب أنفسنا بالتعامل مع الـ for
العادية في حين أن الـ for-each loop
يقوم بنفس العمل بشكل أسهل وأبسط
أنت هنا تقوم بعملية مفاضلة بين الـ for
العادية والـ for-each loop
وترى أيهما يناسبك أكثر
هل تريد الـ index
حين تريد المرور على الأراي ؟ أم لا تحتاج إليه ؟
إذا كنت لا تحتاج الـ index
فالـ for-each loop
هي الأفضل لك
لكن إذا كنت بحاجة للـ index
فالـ for
العادية هي الأفضل لك
بالطبع في لغات مثل الـ TypeScript
فيها العدين من النسخ المشابهه للـ for-each loop
مثل الـ for of
والـ for in
وغيرها
let arr: number[] = [12, 45, 7, -23, 59, 0, -300, 67, -1, 5];
for (let element of arr) {
console.log(element);
}
هنا نرى أننا نستخدم الـ for of
في الـ TypeScript
وكما تلاحظ أنها مطابقة تمامًا للـ for-each loop
في الـ C++
وهي تقوم بنفس العمل وتعطيك قيمة العنصر مباشرةً بدون الحاجة للـ index
في لغة الـ PHP
تجد الـ for-each loop
تسمى foreach
وهي تعمل بنفس الطريقة
$arr = [12, 45, 7, -23, 59, 0, -300, 67, -1, 5];
foreach ($arr as $element) {
echo $element;
}
في الـ Python
تجد الـ for-each loop
تسمى for in
وهي تعمل بنفس الطريقة
arr = [12, 45, 7, -23, 59, 0, -300, 67, -1, 5]
for element in arr:
print(element)
لاحظ أنه كما قلت أن كل لغة لها طريقتها الخاصة في بناء الـ for-each loop
ولكن الفكرة العامة واحدة
قد يختلف الاسم والشكل وطريقة الاستخدام في بعض الأحيان ولكن الفكرة العامة واحدة والأساس واحد
هل هذا كل شيء ؟
بالطبع لا هذه فقط بعض الأمثلة البسيطة التي توضح لك كيفية استخدام الـ Loops
مع الأراي
مع بعض الأفكار والمسائل الجميله التي قد تصادفك في مسيرتك البرمجية
هدفي هنا فقط هو توسيع أفكارك ومساعدتك في فهم كيفية استخدام الـ Loops
مع الأراي
وكيفية حل بعض المسائل البرمجية والتفكير في ايجاد حل وتطبيقه