المحتوى عن 'array'.



مزيد من الخيارات

  • ابحث بالكلمات المفتاحية

    أضف وسومًا وافصل بينها بفواصل ","
  • ابحث باسم الكاتب

نوع المُحتوى


التصنيفات

  • التخطيط وسير العمل
  • التمويل
  • فريق العمل
  • دراسة حالات
  • نصائح وإرشادات
  • التعامل مع العملاء
  • التعهيد الخارجي
  • التجارة الإلكترونية
  • الإدارة والقيادة
  • مقالات ريادة أعمال عامة

التصنيفات

  • PHP
    • Laravel
    • ووردبريس
  • جافاسكريبت
    • Node.js
    • jQuery
    • AngularJS
    • Cordova
  • HTML
    • HTML5
  • CSS
  • SQL
  • سي شارب #C
    • منصة Xamarin
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • Sass
    • إطار عمل Bootstrap
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • لغة Kotlin
  • برمجة أندرويد
  • لغة Swift
  • لغة R
  • لغة TypeScript
  • سير العمل
    • Git
  • صناعة الألعاب
    • Unity3D
  • مقالات برمجة عامة

التصنيفات

  • تجربة المستخدم
  • الرسوميات
    • إنكسكيب
    • أدوبي إليستريتور
    • كوريل درو
  • التصميم الجرافيكي
    • أدوبي فوتوشوب
    • أدوبي إن ديزاين
    • جيمب
  • التصميم ثلاثي الأبعاد
    • 3Ds Max
    • Blender
  • نصائح وإرشادات
  • مقالات تصميم عامة

التصنيفات

  • خواديم
    • الويب HTTP
    • قواعد البيانات
    • البريد الإلكتروني
    • DNS
    • Samba
  • الحوسبة السّحابية
    • Docker
  • إدارة الإعدادات والنّشر
    • Chef
    • Puppet
    • Ansible
  • لينكس
  • FreeBSD
  • حماية
    • الجدران النارية
    • VPN
    • SSH
  • مقالات DevOps عامة

التصنيفات

  • التسويق بالأداء
    • أدوات تحليل الزوار
  • تهيئة محركات البحث SEO
  • الشبكات الاجتماعية
  • التسويق بالبريد الالكتروني
  • التسويق الضمني
  • التسويق بالرسائل النصية القصيرة
  • استسراع النمو
  • المبيعات
  • تجارب ونصائح

التصنيفات

  • إدارة مالية
  • الإنتاجية
  • تجارب
  • مشاريع جانبية
  • التعامل مع العملاء
  • الحفاظ على الصحة
  • التسويق الذاتي
  • مقالات عمل حر عامة

التصنيفات

  • الإنتاجية وسير العمل
    • مايكروسوفت أوفيس
    • ليبر أوفيس
    • جوجل درايف
    • شيربوينت
    • Evernote
    • Trello
  • تطبيقات الويب
    • ووردبريس
    • ماجنتو
  • أندرويد
  • iOS
  • macOS
  • ويندوز

التصنيفات

  • شهادات سيسكو
    • CCNA
  • شهادات مايكروسوفت
  • شهادات Amazon Web Services
  • شهادات ريدهات
    • RHCSA
  • شهادات CompTIA
  • مقالات عامة

أسئلة وأجوبة

  • الأقسام
    • أسئلة ريادة الأعمال
    • أسئلة العمل الحر
    • أسئلة التسويق والمبيعات
    • أسئلة البرمجة
    • أسئلة التصميم
    • أسئلة DevOps
    • أسئلة البرامج والتطبيقات
    • أسئلة الشهادات المتخصصة

التصنيفات

  • ريادة الأعمال
  • العمل الحر
  • التسويق والمبيعات
  • البرمجة
  • التصميم
  • DevOps

تمّ العثور على 4 نتائج

  1. نواصل في هذا المقال استعراض أساسيات لغة جافا التي يحتاج كل مُطوّر أندرويد الإلمام بها. إذا لم تطّلع على الجزء الأول فأنصحك بقراءته أوّلا قبل مواصلة قراءة هذا المقال. المصفوفات في بعض الأحيان نحتاج إلى تخزين عدة بيانات من نفس النوع والتعامل معها، في هذه الحالة لا يتم استخدام عدة متغيرات للتعامل معها ولكن يتم استخدام المصفوفات Arrays. فالمصفوفات مجموعة متغيرات من نفس النوع وتربطها علاقة ببعضها فيتم تخزينها داخل متغير واحد من النوع مصفوفة، ويتم تعريف المصفوفة بالشكل التالي DataType [] arrayName = new DataType [arraySize]; فمثلا لتعريف مصفوفة من النوع int وتحتوي على 6 عناصر: int [] numArr = new int [6]; هكذا تم حجز 6 أماكن في الذاكرة للمصفوفة numArr، وللوصول لهذه الأماكن للتخزين فيها أو التعامل مع قيمها. numArr[0] = 10; numArr[1] = 5; ... numArr[5] = 3; والعنصر الأول يبدأ من صفر وتنتهي العناصر عند الرقم 5 لتصبح ست عناصر، ويتم التعامل بعد ذلك مع عناصر المصفوفة مثل المتغيرات فمثلًا لجمع رقم ما على إحدى قيمها numArr[3] = numArr[0] + 4; ويتم احتساب خطأ إذا تم الوصول إلى عنصر خارج حدود المصفوفة التي تم تعريفها مثل: numArr[7] = 2 ; //Error وتصنف النوع السابق من المصفوفات على أنه من المصفوفات الساكنة التي عند تحديد عدد عناصرها عند تعريفها فلا يمكن زيادة هذا العدد أو إزالة عناصر من المصفوفة. الدوال الدالة هي مجموعة من الأوامر التي تنفذ فقط عندما نقوم باستدعائها وتستخدم للقيام بالأوامر التي يتكرر استخدامها في مواضع مختلفة في البرنامج بسهولة دون إعادة كتابة الأسطر البرمجية مجددًا مما يجعل البرنامج أكثر وضوحًا. تتميز جافا باحتوائها على مجموعة كبيرة من الدوال الجاهزة التي يمكنك استعمالها مباشرة، كما يمكننا من إنشاء دوال خاصة تؤدي وظائف محددة. تعريف الدوال يتم على النحو التالي AccessModifier ReturnType methodName ( parameters List){ //Do some Actions here } ويحدد AccessModifier طريقة الوصول لهذه الدالة. ونوع البيانات التي سترجعه الدالة يتم تحديده في ReturnType. ثم يتم تحديد الاسم الخاص بالدالة، والـ parameters هي البيانات التي يتم تمريرها للدالة. public int add( int a , int b ) { int sum = a + b; return sum; } في المثال السابق كلمة public تعني أن هذه الدالة يمكن استدعاؤها من أي مكان في البرنامج وهي عكس private والتي تعني أن هذه الدالة لا يمكن استدعاؤها إلا من داخل الصّنف class الذي قام بتعريفها. بعد ذلك تم تحديد النوع الذي ستعيده الدالة عند استدعائها وهو int، والاسم الخاص بهذه الدالة add وتأخذ هذه الدالة قيمتين من النوع int لتعيد ناتج جمعهما. لاستدعاء هذه الدالة من أي مكان داخل البرنامج يتم كتابة اسم الدالة كما بالشكل: int result = add (10 , 15); الأصناف وهو الوحدة الأساسية المبني عليها باقي مفاهيم البرمجة كائنية التّوجّه، وهو عبارة عن وعاء كبير يحتوي على متغيرات ودوال وكائنات. وعند تعريف صنف Class جديد يصبح لديك نوع بيانات جديد يمكنك استخدامه مع باق الأنواع الموجودة بالفعل. لتعريف صنف يتم كتابة كلمة class واختيار اسم له، ثم فتح أقواس تحدد بدايته ونهايته. class ClassName { } تسمى المتغيرات التي يتم تعريفها داخل الصّنف بالخصائص attributes، وتسمى الدوال بالتّوابع methods (يعني سنستعمل "دالة" و "تابع" للدّلالة على نفس المفهوم). وتسمى المتغيرات من الأصناف بالكائنات Objects، فلا يمكن إنشاء كائن دون وجود صنف له. إذا أردنا أن نكتب برنامجًا يعبر عن مكتبة وما تحتويه من كتب فيمكن اعتبار الكتاب على أنه كائن ولإنشاء هذا الكائن ينبغي وجود Class له يحتوي على الخصائص الأساسية لجميع الكتب. class Book{ private String bookName; private String authorName; private int bookCode; public void setBookName(String name){ bookName = name; } public String getBookName(){ return bookName; } public void setAuthorName(String name){ authorName = name; } public String getAuthorName(){ return authorName; } public void setBookCode(int code){ bookCode= code } public int getBookCode(){ return bookCode; } } هكذا قمنا بصنع الصّنف الأساسي لجميع الكتب ويحتوي على خصائص مثل اسم الكتاب واسم الكاتب وهذه البيانات معرّفة private أي كما ذكرنا سابقًا لا يمكن الوصول لها أو تغييرها إلا داخل الصّنف المعرّفة بداخله فقط، وهناك عدة توابع فمنها ما يقوم بتخزين قيم في المتغيرات الخاصة بصنف ومنها ما يعيد القيم المخزنة. لاحظ أننا قمنا بتعريف التوابع كـ public وذلك حتى نستطيع الوصول لها واستدعائها من أي مكان في البرنامج. هناك بعض الدوال التي تم تعريف نوع المُخرجات returnType لها من النوع void وتعني أنها لا تعيد شيئًا. ولإنشاء كائن من هذا الصّنف نكتب: Book b1 = new Book(); Book book2 = new Book(); النصف الأيسر كما اعتدنا سابقًا عند إنشاء متغير جديد، أما النصف الأيمن فيتكون من شقين كلمة new وتعني إنشاء هذا المتغير وحجز مساحة له في الذاكرة واسم الصّنف وبعده أقواس وهو ما يسمى بالـ Constructor. ولأي من هذه الكائنات إذا أردنا وضع قيم للخصائص التي بداخلها يتم على النحو التالي: b1.setBookName(“Learn Java”); book2.setBookName(“Intro to programming Language”); book2.setBookCode(101); String name = b1.getBookName(); وهذه بعض الأمثلة لكيفية استدعاء التّوابع المختلفة من داخل class وباستخدام الكائن، لكل كائن خصائصه الخاصة لا يتشارك فيها مع باق الكائنات التي من نفس Class فلكل منها اسم كتاب يتم تخزين فيه نص معين لا يتشاركان فيه. ولاستدعاء التوابع يتم استخدام (.) بعد اسم الكائن ثم كتابة اسم التابع وتمرير المتغيرات التي تتعامل معها إن وجدت حسب تعريفنا للتّابع داخل الصّنف. لاحظ أن عند إنشاء صنف جديد نبدأ اسمه بحرف كبير دائمًا، ويمكنك إنشاء أي عدد من الكائنات من الصّنف كما ذكرنا في المثال السابق. تابع البناء Constructor تتواجد داخل كل صنف تابع خاص يُدعى Constructor يتم استدعاؤه أثناء إنشاء كائن جديد فهو تابع مهم جدًا لإنشاء الكائنات ويقوم المترجم بإنشاء هذا تابع بناء فارغ بشكل افتراضي إذا لم يتم تعريفها من قبل المطوّر. وتكتب كالتالي: public ClassName(parameter List){ //Do some Actions here } يجب أن يكون اسم تابع البناءconstructor نفس اسم الصنف ومن النوع public ويمكنك تعريف أكثر من constructor داخل نفس الصّنف ولا يوجد نوع إرجاع returnType لـلـ constructor. يمكننا من خلال constructor إدخال قيم مباشرة في الخصائص الموجودة في الكائن بدلًا من استدعاء دالة لكل خاصية. class Book{ private String bookName; private String authorName; private int bookCode; public Book(String name,String author,int code){ bookName = name; authorName = author; bookCode = code; } public String getBookName(){ return bookName; } public String getAuthorName(){ return authorName; } public int getBookCode(){ return bookCode; } } في كل مرة يتم إنشاء كائن جديد، يجب استدعاء تابع البناء constructor حتى يتم إنشاء هذا الكائن. لإنشاء كائنات بعد هذا التعديل: Book b1 = new Book (“Learn Java”,”M.K Dave”, 150); هنا تم تعريف كافة الخصائص لحظة إنشاء الكائن، ويتم التعامل مع هذا الكائن بشكل طبيعي كما تعاملنا معه مسبقًا. الوراثة يعتبر مفهوم الوراثة من أهم المفاهيم في البرمجة كائنية التّوجّه ويعني يمكننا إنشاء أصناف ترث من صنف آخر الخصائص والتّوابع المتواجدة به دون تعريفها من جديد، مما يسمح بالتركيز على الخصائص والتّوابع التي يتميز بها الصّنف الجديد. وتستخدم الكلمة extends لتطبيق مفهوم الوراثة: class Shape{ protected int width; protected int height; public void setWidth(int a){ width = a; } public void setHeight(int b){ height = b; } } إذا كان لدينا هذا الصّنف وهو يُمثل شكلًا عامًا له طول وعرض وأردنا أن ننشئ شكلًا آخر (مربع) يرث من هذا الصّنف ويضيف خصائص أكثر: class Square extends Shape{ public int getArea(){ return width * height; } } وبذلك أصبح Square يحتوي على الدالتين setWidth و setHeight بالإضافة للدالة الجديدة التي قام بتعريفها getArea، وبذلك استطعنا أن نعطي المزيد من الخصائص للشكل الجديد. وإذا أردنا أن نصنع شكلًا آخر (مثلث): class Triangle extends Shape{ public int getArea(){ return 0.5*width * height; } } لا يمكن للصّنف أن يرث من أكثر من أب. وبتطبيق هذا المفهوم على الدرس السابق نجد أن أندرويد يحتوي على صنف اسمه View وهو الأب لكل العناصر الخاصة بواجهة المستخدم ويحدد الخصائص الأساسية والمشتركة بينهم جميعًا ويرث منه العناصر الخاصة مثل TextView وهو View ولكن يعرض نصًا فقط أو Button وأيًضا View قابل للضغط ويقوم بمهمة محددة عند الضغط عليه. وإذا قمنا بالتعديل على المثال السابق واستخدمنا في Shape تابع البناء لتعريف الطول والعرض: class Shape{ protected int width; protected int height; public Shape(int a ,int b){ width = a; height = b; } } ينبغي علينا أن نعرف دالة بناء للصّنف التي ترث منه: class Square extends Shape{ public Shape(int w ,int h){ super(w,h); } public int getArea(){ return width * height; } } وتستخدم super لاستدعاء Constructor الخاص بالأب وتمرير له القيم التي يحتاجها، وذلك لأن عند إنشاء كائن من Square والذي يرث من Shape: Sqaure s = new Square(10,10); يتم بناء الأب أولًا Shape ثم الابن Square حتى يكتمل بناء الكائن s بشكل صحيح. لذا يتم تمرير في دالة البناء الخاصة بالابن ما تحتاجه دالة البناء الخاصة بالأب، ولم نقوم بذلك قبل التعديل لأننا كنا نستعمل دالة بناء فارغة في الأب. التحويل من نوع بيانات إلى آخر تمكننا لغات البرمجة من التحويل من نوع بيانات إلى آخر باستخدام مفهوم Casting، فمثلًا إذا كان لدينا متغير من النوع double: double d = 12.5478; ونريد تحويله إلى رقم صحيح: int x = (int) d; نفعل ذلك عن طريق كتابة نوع المتغير بين القوسين وبعدها اسم المتغير الذي نريد تحويله كما في المثال. وهناك بعض الشروط على التحويل بين الأنواع بهذه الطريقة فلا يمكن تحويل String إلى int مثلًا لاختلاف النوعين عن بعضهما. ويمكن تحويل من صنف إلى آخر شريطة أن يكون بينهما علاقة الوراثة. Shape sh = new Shape(15,15); Square s = (Square) sh; بهذا نكون قد وصلنا إلى نهاية هذا الدّرس، في انتظار تجربتكم وآرائكم. إن كانت لديك أيّة أسئلة فلا تتردّد في طرحها.
  2. تعتبر المصفوفات من بنى المعطيات المهمّة في أيّ لغة برمجة. سيفترض هذا الدرس أنّه لديك خبرة مسبقة عن مفهوم المصفوفة. المصفوفات في سي شارب هي عبارة عن نوع مرجعيّ reference type، وهي ترث من الصنف الأب System.Array. تقدّم لنا سي شارب المصفوفات بأسلوب مبسّط وواضح. فلتعريف مصفوفة يمكنها استيعاب 10 عناصر من النوع int مثلًا يكفي أن نكتب ما يلي: int[] arrIntegers = new int[10]; للعبارة السابقة في الواقع وظيفتان: الأولى هي التصريح عن المتغيّر arrIntegers على أنّه مصفوفة عناصرها من النوع int وذلك عن طريق كتابة []int أوّل العبارة. والثانية هي إنشاء كائن المصفوفة وحجز 10 أماكن في الذاكرة بحيث يستطيع كلّ مكان منها استيعاب قيمة من النوع int وذلك عن طريق التعبير [new int[10 ومن ثمّ إسناد المرجع لهذا الكائن إلى المتغير arrIntegers. ويمكن كما نعلم أن نجري هذه العمليّة على شكل عبارتين منفصلتين. يمكننا إنشاء أيّ نوع من المصفوفات نرغبه. فيمكننا إنشاء مصفوفات عناصرها نصوص []string، ومصفوفات عناصرها أعداد ذوات فاصلة عائمة مثل []float، وحتى يمكننا إنشاء مصفوفات عناصرها كائنات من أصناف ننشئها نحن بأنفسنا. فمثلًا إذا أنشأنا الصنف Car فيمكننا إنشاء مصفوفة من العناصر التي يقبل كل عنصر منها أن يخزّن مرجع لكائن من الصنف Car وذلك على الشكل التالي: Car[] arrCars = new Car[5]; تُنشئ العبارة السابقة المصفوفة arrCars والتي تحوي 5 عناصر يمكنها تخزين مراجع لكائنات من الصنف Car. استخدام المصفوفات مع أنواع مضمنة لكلّ عنصر في مصفوفة دليل index، ويُعبّر عن ترتيب هذا العنصر ضمن المصفوفة. يبدأ ترقيم الأدلّة في أيّ مصفوفة بالصفر. أي أنّ دليل العنصر الأوّل هو الصفر. فالمصفوفة arrCars التي صرّحنا عنها قبل قليل تحتوي على خمسة عناصر، دليل العنصر الأوّل هو 0، أمّا دليل العنصر الأخير فهو 4 كما هو واضح. يمكن المرور على عناصر أيّ مصفوفة باستخدام الدليل. فمثلًا يمكننا الوصول إلى العنصر الثاني في المصفوفة arrCars عن طريق كتابة [arrCars[1. يطلب البرنامج Lesson09_01 التالي من المستخدم إدخال درجات 5 طلاب في إحدى المواد الدراسيّة ومن ثمّ يحسب معدّل هؤلاء الطلبة في هذه المادّة، على افتراض أنّ الدرجة العظمى هي 100. ومن ثمّ يطبع المعدّل مع أسماء الطلاب ودرجاتهم على الشاشة: 1 using System; 2 3 namespace Lesson09_01 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 int[] arrMarks = new int[5]; 10 string[] arrNames = new string[5]; 11 int sum = 0; 12 13 Console.WriteLine("Input Students Marks"); 14 Console.WriteLine("====================="); 15 16 //input loop. 17 for(int i = 0; i < arrMarks.Length; i++) 18 { 19 Console.Write("Input student {0} th name: ", i + 1); 20 arrNames[i] = Console.ReadLine(); 21 22 Console.Write("Input student {0} th mark: ", i + 1); 23 string tmpMark = Console.ReadLine(); 24 arrMarks[i] = int.Parse(tmpMark); 25 26 Console.WriteLine(); 27 } 28 29 Console.WriteLine(); 30 Console.WriteLine("Students Marks Table"); 31 Console.WriteLine("===================="); 32 Console.WriteLine("No\tName\tMark"); 33 34 //calculating sum and display output loop. 35 for (int i = 0; i < arrMarks.Length; i++) 36 { 37 sum += arrMarks[i]; 38 Console.WriteLine("{0}\t{1}\t{2}", i + 1, arrNames[i], arrMarks[i]); 39 } 40 41 Console.WriteLine("-------------------"); 42 Console.WriteLine("Sum\t\t{0}", sum); 43 Console.WriteLine("Average\t\t{0}", sum/(double)arrMarks.Length); 44 Console.WriteLine(); 45 } 46 } 47 } يبدأ البرنامج السابق بالتصريح عن المصفوفتين arrMarks لتخزين علامات الطلّاب و arrNames لتخزين أسمائهم. كما يصرّح عن المتغيّر sum لتخزين مجموع الدرجات. يعرض البرنامج عبارتين توضيحيّتين في السطرين 13 و 14، ثمّ تبدأ حلقة for في السطر 17 بجمع أسماء ودرجات الطلّاب في هذه المادّة. لاحظ كيف أنّنا وضعنا شرط استمرار الحلقة i < arrMarks.Length (السطر 17). تعطينا الخاصيّة Length للمصفوفة arrMarks عدد العناصر ضمن هذه المصفوفة (عددها 5 في مثالنا). سيضمن ذلك تنفيذ حلقة for لخمسة مرّات فقط. نبدأ اعتبارًا من السطر 29 بالتجهيز لعرض النتائج، حيث سنظهرها على شكل جدول يضم ثلاثة أعمدة الرقم المتسلسل للطالب No والاسم Name والدرجة Mark. يطبع السطر 32 ترويسة هذا الجدول من خلال النص "No\tName\tMark" نستخدم المحرف t\ في النص السابق لترك مسافة جدولة tab تفصل بين كل عمودين. يدخل البرنامج بعد ذلك إلى حلقة إظهار النتائج اعتبارًا من السطر 35. لاحظ النص التنسيقيّ "{0}\t{1}\t{2}" في السطر 38، وظيفته أيضًا ترك مسافة جدولة بين كل عمودين. بعد الانتهاء من الحلقة نُظهر المجموع Sum والمعدّل Average بقسمة المجموع Sum على عدد الطلاب. أمر أخير تجدر ملاحظته، في السطر 43 عند حساب المعدّل استخدمنا التعبير التالي: sum/(double)arrMarks.Length، ويعود سبب وجود عامل التحويل (double) أمام arrMarks.Length إلى جعل القسمة تجري بين قيمة من نوع int (قيمة sum) وقيمة من نوع double لكي يصبح الناتج من نوع double. لأنّه بدون عامل التحويل هذا، ستجري عمليّة القسمة بين قيمتين من نوع int (الخاصيّة Length هي من نوع int) وبالتالي سيكون الناتج من نوع int وتُهمل أي أجزاء عشريّة وهذا أمر غير مرغوب. لقد نفّذت البرنامج وقمت بتزويده ببعض البيانات، وحصلت عل الخرج التالي: استخدام المصفوفات مع أنواع من إنشاءنا لا تختلف طريقة التعامل مع المصفوفات عناصرها من أنواع مضمّنة مع مصفوفات عناصرها من أصناف موجودة في مكتبة FCL أو حتى من أصناف ننشئها نحن، باستثناء أمرٍ مهمٍ واحد سنتعرّض له. سننشئ لهذا الغرض صنف جديد اسمه Student، يحتوي هذا الصنف على خاصّتين: الاسم Name والدرجة Mark. سنصرّح بعد ذلك عن المتغيّر arrStudents ليكون مصفوفة من النوع []Student. سيسلك هذا البرنامج نفس سلوك البرنامج Lesson09_01 تمامًا، أي سيطلب درجات خمسة طلاب ليعرضهم ويحسب مجموع درجاتهم ومعدّلهم. انظر البرنامج Lesson09_02: 1 using System; 2 3 namespace Lesson09_02 4 { 5 class Student 6 { 7 public string Name { get; set; } 8 public int Mark { get; set; } 9 } 10 11 class Program 12 { 13 static void Main(string[] args) 14 { 15 Student[] arrStudents = new Student[5]; 16 int sum = 0; 17 18 Console.WriteLine("Input Students Marks"); 19 Console.WriteLine("====================="); 20 21 //input loop. 22 for (int i = 0; i < arrStudents.Length; i++) 23 { 24 arrStudents[i] = new Student(); 25 26 Console.Write("Input student {0} th name: ", i + 1); 27 arrStudents[i].Name = Console.ReadLine(); 28 29 Console.Write("Input student {0} th mark: ", i + 1); 30 string tmpMark = Console.ReadLine(); 31 arrStudents[i].Mark = int.Parse(tmpMark); 32 33 Console.WriteLine(); 34 } 35 36 Console.WriteLine(); 37 Console.WriteLine("Students Marks Table"); 38 Console.WriteLine("===================="); 39 Console.WriteLine("No\tName\tMark"); 40 41 //calculating sum and display output loop. 42 for (int i = 0; i < arrStudents.Length; i++) 43 { 44 sum += arrStudents[i].Mark; 45 Console.WriteLine("{0}\t{1}\t{2}", i + 1, arrStudents[i].Name, arrStudents[i].Mark); 46 } 47 48 Console.WriteLine("-------------------"); 49 Console.WriteLine("Sum\t\t{0}", sum); 50 Console.WriteLine("Average\t\t{0}", sum / (double)arrStudents.Length); 51 Console.WriteLine(); 52 } 53 } 54 } كلّ من البرنامجين Lesson09_01 و Lesson09_02 متشابهان من حيث الخرج. ولكن يتعامل البرنامج Lesson09_02 مع المصفوفة arrStudents التي عناصرها من النوع Student. الصنف Student مصرّح عنه في الأسطر من 5 إلى 9. والمصفوفة arrStudents مصرّح عنها في السطر 15. يُعتبر السطر 24 مهمًا جدًا وفيه يتم إنشاء كائن جديد من الصنف Student وإسناده إلى كل عنصر من عناصر المصفوفة arrStudents في كل دورة من دورات حلقة for. إذا حاولت إزالة عبارة إنشاء الكائن من الصنف Student في السطر 24 فسيعمل البرنامج ولكنّه سيتوقّف عن التنفيذ ويصدر خطأ عندما يصل التنفيذ إلى السطر 27. لأنّه عندما نصرّح عن مصفوفة عناصرها من أنواع ليست مضمّنة، فنحن في الحقيقة نصرّح عن متغيّرات فقط دون إنشاء كائنات ضمن هذه العناصر (المتغيّرات). وبالتالي لا يحق لنا الوصول إلى أعضاء كائن غير مُنشَأ أصلًا، فالتعبير arrStudents.Name سيولّد خطأً مالم يكن هناك كائن فعلي ضمن العنصر [arrStudents[i (أي عنصر المصفوفة ذو الدليل i). حلقة foreach التكرارية حلقة foreach من الحلقات التكراريّة المفيدة والتي تتسم بأسلوب عمل أقرب إلى المألوف. يمكن استخدام حلقة foreach على المصفوفات والمجموعات كما سنرى لاحقًا. طريقة استخدام foreach بسيطة سنتناولها من خلال البرنامج Lesson09_03 التالي: 1 using System; 2 3 namespace Lesson09_03 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 int[] arrNumbers = new int[10]; 10 Random random = new Random(); 11 12 for(int i = 0; i < arrNumbers.Length; i++) 13 { 14 arrNumbers[i] = random.Next(100); 15 } 16 17 foreach(int n in arrNumbers) 18 { 19 Console.WriteLine(n); 20 } 21 } 22 } 23 } ملاحظة: البرنامج السابق بسيط، حيث يصرّح عن المصفوفة arrNumbers بعشرة عناصر، ويعمل على تعبئة عناصرها بقيم عشوائيّة يحصل عليها من كائن من النوع Random. صرّحنا عن المتغيّر random وأسندنا إليه مرجع لكائن من الصنف Random وذلك في السطر 10. في حلقة for (الأسطر من 12 إلى 15) قمنا بتوليد أرقام عشوائيّة عن الطريق التابع (Next(100 من الكائن random والذي يولّد أرقامًا عشوائيّة صحيحة غير سالبة أقل من 100. بعد ذلك سنطبع هذه الأرقام العشوائيّة على الشاشة عن طريق حلقة foreach. مبدأ هذه الحلقة بسيط، منطق عملها يتلخّص على النحو التالي: "من أجل كل عنصر n موجود ضمن المصفوفة arrNumbers نفّذ الشيفرة الموجودة في حاضنة foreach". في مثالنا هذا تحتوي الحاضنة على عبارة برمجيّة واحدة (السطر 19). في البرنامج Lesson09_03 السابق المتغيّر n المصرّح عنه في السطر 17 والذي سيحمل قيمة مختلفة من عناصر المصفوفة arrNumbers في كل دورة للحلقة، هو متغيّر للقراءة فقط read-only لا يمكن تغيير قيمته ضمن حاضنة foreach. تمارين داعمة تمرين 1 اكتب برنامجًا يعرّف مصفوفة من نوع int بعشرة عناصر. ثم يطلب من المستخدم إدخال قيم لهذه العناصر. بعد ذلك يعمل البرنامج على ترتيب عناصر هذه المصفوفة تصاعديًّا. تلميح: تمتلك سي شارب أساليب جاهزة وسريعة لمثل عمليّات الترتيب هذه، ولكنّنا نريد في هذا المثال التدرُّب على الحلقات والمصفوفات. تمرين 2 عدّل البرنامج Lesson09_02 السابق لكي يسمح للمستخدم بإدخال بيانات عدد كيفي من الطلّاب. تلميح: ستحتاج لأن تطلب من المستخدم إدخال عدد الطلاب المراد إدخال بياناتهم أولًا، ومن ثمّ تصرّح عن المصفوفة arrStudents بالعدد المطلوب. الخلاصة تعرّفنا في هذا الدرس على المصفوفات وطرق استخدامها. توجد في الحقيقة مزايا أخرى تتمتّع بها المصفوفات مثل إمكانيّة نسخ مصفوفة إلى مصفوفة أخرى، وغيرها من المزايا الأخرى التي سنتناولها في الدروس والسلاسل القادمة. كما تعرّفنا أيضًا على الحلقة التكراريّة foreach التي يُعتبر أسلوب عملها مألوفًا، وهي مفيدة جدًا عند استخدامها مع المجموعات كما سنرى لاحقًا.
  3. php 101

    سنعلم في هذا الدرس عن المصفوفات وحلقة foreach. لنفترض أنَّك تريد أن تُخزِّن مقدارًا كبيرًا من البيانات؛ أول 10000 من مضاعفات الرقم 5 على سبيل المثال، فعليك أنَّ تُعرِّف 10000 متغير لهم 10000 اسم؛ وهذه مهمة صعبة ومضنية بالتأكيد. أحد الحلول هو تخزين البيانات في مصفوفة، إذ يمكننا تخزين أي عدد نريده من القيم في مصفوفة وحيدة فقط! لنلقِ نظرةً عن آلية عمل المصفوفات. <?php // تعريف مصفوفة ذات ثلاثة عناصر $type1 = array('first element', 'second element', 'third element'); // نستعمل الدالة print_r لطباعة جميع عناصر المصفوفة // الناتج: Array ( [0] => first element [1] => second element [2] => third element ) print_r($type1); echo "<br>"; // نستعمل المفاتيح (الفهارس) للوصول إلى قيم معيّنة في المصفوفة // لاحظ أنَّ المفاتيح رقمية من 0 حتى 2 echo $type1[0]; echo "<br>"; echo $type1[1]; echo "<br>"; echo $type1[2]; echo "<br>"; ?> في السطر الثالث من الشيفرة السابقة، عرَّفنا مصفوفةً اسمها ‎ $type1وملأناها بثلاث قيم (first element، و second element، و third element). كيف يمكننا استعمالها الآن؟ كل قيمة من القيم المُخزَّنة في المصفوفة مرتبطة بمُعرِّف فريد يسمى الفهرس (index)؛ يمكنك الوصول إلى تلك القيم عبر الفهرس الخاص بها. يطبع السطر السابع في المثال السابق المصفوفة بأكملها باستعمال الدالة print_r()‎، وسترى أنَّه على الرغم من أنَّك قد ملأت القيم فقط، لكنك ستحصل أيضًا على أرقامٍ تبدأ من الصفر وترتبط بتلك القيم؛ وفي الواقع، تلك الأرقام هي الرقم التسلسلي للقيمة (تذكر أننا نبدأ العد في البرمجة من الرقم 0 بدلًا من 1). ثم قمنا بطباعة القيم التي خزناها في الموضع 0 و 1 و 2 على التوالي وبالترتيب. المصفوفات الترابطية استخدمنا الفهارس الافتراضية في المثال السابق (0، و 1، و2)، لكن يمكننا أن نُعرِّف الفهارس يدويًا كما في المثال الآتي: <?php // طريقةٌ أخرى لتعريف مصفوفة $type2 = array('key'=>'value', 'key2'=>'value2', 'key3'=> 'value3'); // الناتج: Array ( [key] => value [key2] => value2 [key3] => value3 ) print_r($type2); echo "<br>"; // المفاتيح هنا نصيّة، وهي key1، و key2، و key3 echo $type2['key3']; ?> عرَّفنا في المثال السابق الفهارس الخاصة بنا (تُسمى أيضًا المفاتيح [keys]) التي ترتبط مع تلك القيم. يسمى هذا النوع من المصفوفات بالمصفوفات ترابطية (associative arrays). الوصول إلى عناصر المصفوفات تُعتبَر كل قيمة في المصفوفة متغيرًا مستقلًا، فيمكننا أن نجري جميع العمليات التي يمكن القيام بها على المتغيرات (كالزيادة والنقصان وإسناد القيم …إلخ.): <?php // نعرِّف مصفوفةً فارغةً $arr = array(); // يمكننا إسناد البيانات إلى عناصر المصفوفة كما يلي $arr[0] = 'academy'; $arr[1] = 'hsoub'; // قد لا تكون المفاتيح ذات أرقام متتالية (لاحظ عدم وجود المفتاحين 2 و 3) $arr[4] = 'com'; // يمكننا استعمال نمطي المفاتيح (الرقمية والنصية) في نفس المصفوفة $arr['day'] = 'Monday'; $arr['num1'] = 4; $arr['num2'] = 5; // كل عنصر في المصفوفة مستقل تمامًا عما سواه $arr['num3'] = $arr['num1'] + $arr['num2']; // سنطبع كامل المصفوفة باستعمال print_r print_r($arr); ?> لاحظ كيف أننا عرفنا بدايةً مصفوفةً فارغة، ثم أضفنا عناصرها بذكر المتغير الحاوي على مصفوفة متبوعًا بأقواسٍ مربعة ([]) بداخلها مفتاح العنصر. يجدر بالذكر أننا نستطيع أن نستعمل مفاتيح رقمية ونصية في نفس المصفوفة. إذا أردنا أن نجعل PHP تُرقِّم عناصر المصفوفة تلقائيًا عند إسناد قيم لها، فيكفي أن نضع أقواسًا مربعة فارغة كما يلي: <?php // نعرِّف مصفوفةً فارغةً $arr = array(); // يمكننا جعل PHP تُرقِّم العناصر تلقائيًا كما يلي $arr[] = 'academy'; $arr[] = 'hsoub'; $arr[] = 'com'; // سنطبع كامل المصفوفة باستعمال print_r // الناتج: Array ( [0] => academy [1] => hsoub [2] => com ) print_r($arr); ?> يجدر بالذكر أننا نستطيع أن ندرج قيمة عنصر من عناصر المصفوفة في سلسلةٍ نصيةٍ مباشرةً كما في المتغيرات (أي يجب أن تكون علامة الاقتباس مزدوجةً) لكن علينا في المصفوفات أن نحيط اسم العنصر بقوسين معقوفين كما يلي (لاحظ أننا استعملنا الطريقة الأكثر شيوعًا الآن في تعريف المصفوفات، ألا وهي إحاطة عناصر المصفوفة بقوسين مربعين [] كما يظهر في المثال أدناه): المصفوفات والحلقات لنفترض أننا نريد إجراء بعض العمليات على كمية كبيرة من البيانات مخزَّنة في مصفوفة (ولنقل أننا نريد طباعة البيانات، أو حساب مجموع الأرقام الموجودة في المصفوفة)؛ فسنستعمل لهذا الغرض الحلقات، لنلقِ نظرةً على مثالٍ عن حلقة for: <?php $a = [1, 21, 23, 43, 32, 23, 4]; // عناصر المصفوفة هي: $a[0], $a[1], $a[2]... // سنُهيِّئ متغيرًا للمجموع ونسند إليه القيمة 0 $sum = 0; for($i = 0; $i < 7; $i++) { // ستزداد قيمة المتغير $i في كل تكرار للحلقة // أي أن قيمته ستتغير إلى قيمة مفتاح العنصر التالي في المصفوفة $sum += $a[$i]; } echo $sum; ?> أنصحك بأن تُعيد حلّ المثال السابق باستعمال حلقتَيّ while و do-while من درس الحلقات لكي تتدرب على استعمالها. هنالك حلقةٌ إضافيةٌ في PHP وُضِعَت خصيصًا للمصفوفات، اسمها حلقة foreach. إذ تبدأ هذه الحلقة من أول عنصر في المصفوفة وتنتهي بآخر عنصر فيها. لنعد كتابة المثال السابق باستخدام حلقة foreach: <?php $a = [1, 21, 23, 43, 32, 23, 4]; // عناصر المصفوفة هي: $a[0], $a[1], $a[2]... // سنُهيِّئ متغيرًا للمجموع ونسند إليه القيمة 0 $sum = 0; foreach ($a as $v) { // لو كنا نستعمل حلقة من نوع آخر، لكنا قد كتبنا // $v = $a[$i]; // $sum += $v; // i++; $sum += $v; } echo $sum; ?> نُسنِد -في كل تكرار للحلقة- قيمةً جديدةً للمتغير الذي اسمه ‎$v ونعطيه قيمة العنصر التالي في المصفوفة ‎$a؛ حلقة foreach مفيدة جدًا عندما لا تعرف عدد العناصر الموجودة في المصفوفة، أو إذا كنت تستعمل مصفوفة ترابطية (associative arrays). حلقة foreach مع المصفوفات الترابطية أما في حالة المصفوفات الترابطية، فعلينا تعريف متغيرين (بدلًا من واحد) لأننا لا نعلم قيمة الفهرس (أو المفتاح [key]) لكل عنصر. أول متغير نُعرِّفه هو المفتاح، والثاني هو القيمة التي ترتبط به. الشكل العام لحلقة foreach هو: foreach (array as $key => $value) { statements } تمعّن في المثال الآتي وانظر كيف أُسنِد المفتاح إلى متغير، وأُسنِدَت قيمته إلى متغيرٍ آخر؛ يجدر بالذكر أنَّ المصفوفة المستعملة هي مصفوفة متعددة الأبعاد، أي أنَّ قيمة العنصر هي بدورها مصفوفةٌ أخرى، ولا مانع من استعمال حلقة foreach داخل حلقة foreach أخرى إن دعت الضرورة إلى ذلك. <?php // نُعرِّف مصفوفة ذات بعدين $arr = [ 'student1' => array('SN' => 16472, 'math_grade' => 'A+'), 'student2' => array('SN' => 16483, 'math_grade' => 'C'), 'student3' => array('SN' => 16587, 'math_grade' => 'A') ]; // حلقة foreach تمر على جميع عناصر المصفوفة الرئيسية foreach ($arr as $student => $info) { // لاحظ كيف أنَّ القيمة المُنسدَة إلى المتغير $info هي مصفوفة أخرى echo "the serial number for $student is {$info['SN']}, and he got {$info['math_grade']} grade in math!"; } ?> دوال التعامل مع المصفوفات ألم تتساءل كيف سنعلم إن كانت المصفوفة تحتوي عنصرًا ما أم لا؟ ربما فكرت باستعمال حلقةٍ ما للمرور على جميع عناصر المصفوفة، لكن PHP تسهِّل عليك الأمر وتوفر لك دالةً لاختبار وجود عنصرٍ ما في المصفوفة ألا وهي الدالةin_array() ‎ التي تقبل وسيطين أولهما هو القيمة التي سيُبحَث عنها، وثانيهما هي المصفوفة التي سيُبحَث فيها؛ وستعيد هذه الدالة القيمة TRUE إن وجِدَت تلك القيمة في المصفوفة، و FALSE خلا ذلك. أما لو أردت معرفة إن كان مفتاحٌ ما موجودًا في المصفوفة، فاستعمل الدالةarray_key_exists() ‎ التي تقبل وسيطين أيضًا أولهما هو المفتاح الذي يُبحَث عنه، وثانيهما هو المصفوفة التي سيُبحَث فيها؛ وستعيد هذه الدالة TRUE إن وجد ذاك المفتاح، و FALSE عدا ذلك. مثالٌ عن استعمالهما: <?php $arr = ['subdomain' => 'academy', 'domain' => 'hsoub', 'root_domain' => 'com']; // التحقق إن كانت القيمة «hsoub» موجودةً في المصفوفة if (in_array('hsoub', $arr)) { echo '"hsoub" value found'; } if (array_key_exists('subdomain', $arr)) { echo '"subdomain" key found'; } ?> هل تتذكر كيف قسّمنا السلاسل النصية إلى قسمين يفصل بينهما محرف معيّن في درس السلاسل النصية وحصلنا على الجزء الواقع بعد ذاك المحرف؟ الدالة explode()‎ تفعل المِثل، لكنها تُخزِّن الناتج في مصفوفة، حيث تقبل وسيطين أولهما هو السلسلة النصية التي تُمثِّل الفاصل بين عناصر المصفوفة، وثانيهما هو السلسلة النصية التي تريد تقسيمها؛ انظر إلى ناتج المثال الآتي لإزالة الغموض عن الكلام السابق: <?php $str = 'hsoub academy is the best academy ever'; // سنقسم السلسلة النصية السابقة عند كلمة is، ثم سنطبع مخرجاتها $arr1 = explode('is', $str); // الناتج: Array ( [0] => hsoub academy [1] => the best academy ever ) print_r($arr1); // سنقسم السلسلة النصية السابقة عند كلمة academy، مما يُنتِج ثلاثة عناصر في المصفوفة $arr2 = explode('academy', $str); // الناتج: Array ( [0] => hsoub [1] => is the best [2] => ever ) print_r($arr2); ?> أما لو أردت دمج عناصر المصفوفة وتحويلها إلى سلسلة نصية، فاستعمل الدالة implode()‎؛ التي لها شكلان عامان أحدهما يقبل وسيطًا وحيدًا هو المصفوفة التي تريد تحويلها إلى سلسلة نصية؛ والشكل الثاني يقبل وسيطين أولهما هو السلسلة النصية التي ستوضع بين عناصر المصفوفة وثانيهما هو المصفوفة التي تريد تحويلها إلى سلسلة نصية. <?php $arr = ['academy', 'hsoub', 'com']; // إن استعملنا implode ذات الشكل الأول، فسنحصل على academyhsoubcom $str1 = implode($arr); echo $str1; // أما لو استعملنا الشكل الثاني، ومررنا «.» كوسيط، فسنحصل على academy.hsoub.com $str2 = implode('.', $arr); echo $str2; ?> يُلخِّص الجدول الآتي بعض دوال المصفوفات الشهيرة:. table{border: 1px solid, black; border-collapse: collapse;} th, td{border: 1px solid black;padding: 5px 10px;} th{background-color: #fbfcfc;} الدالة شرحها array_merge()‎ يُمرَّر إليها أكثر من مصفوفة كوسيط مهمتها هي دمج تلك المصفوفات مع بعضها بعضًا وإعادة المصفوفة الناتجة array_rand()‎‎ اختيار قيمة عشوائية واحدة أو أكثر تقبل وسيطًا إجباريًا هو المصفوفة التي ستؤخذ القيمة العشوائية منها ووسيطًا اختياريًا يُحدِّد عدد القيم التي ستُعاد تُعيد سلسلةً نصيةً تحوي مفتاح العنصر العشوائي المُختار إن اختارت قيمةً عشوائيةً وحيدة تعيد مصفوفة بمفاتيح العناصر العشوائية إن كان الوسيط الثاني أكبر من 1 ()array_search تبحث في المصفوفة عن قيمة مُعيّنة وستُعيد المفتاح المقابل لها إن وُجِدَت تقبل وسيطين أولهما هو القيمة التي ستبحث عنها، وثانيهما هو المصفوفة التي سيُبحَث فيها array_sum()‎ حساب مجموع القيم العددية في مصفوفة تقبل وسيطًا وحيدًا هو المصفوفة المُراد حساب مجموع الأعداد فيها ()array_unique تُزيل هذه الدالة جميع التكرارات في مصفوفة تُمرَّر إليها كوسيط ()count ربما هذه من أهم الدوال السابقة، إذ تُعيد عدد العناصر الموجودة في مصفوفة تُمرَّر إليها كوسيط. نستفيد كثيرًا من هذه الدالة في حلقة for إن لم نكن نعرف عدد عناصر المصفوفة نستطيع أن نكتب: for (int i=0; i<array.count(); i++) {} تمرين لديك المصفوفة الآتية باسم names: Array ( [16472] => Ayham [16483] => Ameen [15789] => Bashir ) والمصفوفة باسم grades: Array ( [16472] => Array ( [math] => 62 [arabic] => 76 [english] => 75 ) [16483] => Array ( [math] => 85 [arabic] => 71 [english] => 82 ) [15789] => Array ( [math] => 52 [arabic] => 86 [english] => 93 ) ) اكتب برنامجًا يأخذ اسم الطالب ثم يطبع جميع علاماته. المصادر مقال Array and foreach loop in PHP لصاحبه Harish Kumar. كتاب تعلم البرمجة بلغة PHP. صفحات Arrays و array وما هو موجود في Array Functions.
  4. بعض أنواع البيانات التي تحدّثنا عنها في الدروس السّابقة هي السلاسل و الأرقام. تتيح لنا السلاسل إمكانيّة التعامل مع النصوص الخاصّة ببرنامجنا والأرقام تمكننا من التعامل مع البيانات الرقميّة. لنفترض مثلاً أنّنا نريد إنشاء قائمة مشتريات، بداخل تلك القائمة لدينا أسماء المشتريات. يمكننا إنشاء تلك القائمة على شكل سلسلة String مفصول بين كل عنصر فيها بفاصلة. أو يمكننا استخدام ثلاثة سلاسل محفوظة بمتغيّرات مسمّاة item1, item2 وهكذا. ولكن لحسن الحظّ فإنّ روبي تُوفّر لنا نوعًا يمكنه التعامل مع هذا النّوع من البيانات فعلاً يسمّى بالمصفوفة Array. المصفوفة هي عبارة عن حاوية للبيانات. تُستخدم المصفوفات لتخزين أنواع مختلفة من البيانات مثل السلاسل، الأرقام وأيّ نوع آخر من كائنات روبي. سنتعرّف في هذا الدّرس على كيفيّة إنشاء المصفوفات والتّعامل معها في روبي. إنشاء مصفوفة سنستخدم سطر أوامر روبي التفاعليّ الآن للتعرّف على المصفوفات. ابدأ جلسة روبي في الطرفيّة عن طريق كتابة irb والضّغط على Enter. يمكن إنشاء مصفوفة حرفيّة Array Literal عن طريق وضع الكائنات داخل أقواس مربّعة Square Brackets مفصول بينها بفاصلة. كالمثال أدناه، أنشأنا قائمة من الأعداد الأوّليّة: [2, 3, 5, 7] لا تشترط المصفوفات بأن تقوم بتخزين أرقام فقط بها. يمكنك أيضًا إنشاء مصفوفة مكوّنة من سلاسل هكذا: ["apples", "oranges"] هناك أيضًا طريقة أقصر لإنشاء مصفوفة من السلاسل. نبدأ ذلك بكتابة علامة النّسبة المئويّة متبوعة بحرف w ثمّ بعد ذلك يمكنك الاختيار إذا كنت تريد استخدام الأقواس Parentheses أو الحاضنات Curly Brackets لبدء المصفوفة، الأمر الإيجابي حول هذه الطريقة هو أنّه باستخدامها لن تصبح في حاجة إلى وضع كل سلسلة بين علامات اقتباس وأيضًا لن تحتاج إلى الفصل بين عناصر المصفوفة باستخدام الفاصلة، استخدام المسافات يفي بالغرض. %w(apples, oranges) %w{apples oranges} عند كتابة المصفوفة بأحد الطريقتين أعلاه والضّغط على Enter ستلاحظ أنّ روبي ستضعها في الصّورة الافتراضيّة للمصفوفة، أقواس مربّعة ومفصول بين السلاسل بفاصلة. ليس مفروضًا عليك استخدام كائنات من نوع بيانات واحد في المصفوفة فيمكنك إنشاء مصفوفة تحتوي على أكثر من نوع من العناصر، كما تلاحظ في المثال أدناه فقد أنشأنا مصفوفة تحتوي على عدد صحيح Integer، سلسلة وعدد عشري Float: [1, "two", 3.0] هناك طريقة أخرى لإنشاء مصفوفة وذلك باستخدام دالّة new كالتالي: fruits = Array.new ما فعلناه هنا هو إنشاء متغيّر باسم fruits وتعيين مصفوفة جديدة فارغة إلى ذلك المتغيّر باستخدام دالّة new. قد تتساءل، إذا كان بالإمكان تعيين مصفوفة إلى متغيّر فهل يمكن استخدام متغيّر كعنصر في مصفوفة؟ نعم يمكن ذلك ويكون نوع العنصر هو نوع البيانات الموجودة في المتغيّر، جرّب إنشاء متغيّر ثم ضعه في المصفوفة كعنصر كما فعلت سابقًا مع السلاسل، تسمّى هذه العمليّة بالاستيفاء Code Interpolation. item = "apples" fruits = %W(#{item} oranges) لاحظ أنّنا استخدمنا حرف W كبير بدلاً من الصّغير الذي استخدمناه سابقًا. المصفوفات متعددة الأبعاد يمكنك إنشاء مصفوفة تحتوي على مصفوفات أخرى بداخلها، تسمّى بالمصفوفة متعدّدة الأبعاد Multidimensional Array. يعد هذا النوع من المصفوفات مفيدًا لإنشاء مستوى إحداثيّات. يمكن إنشاء مصفوفة متعدّدة الأبعاد هكذا: [[1, 3], [5, 7]] الوصول إلى عنصر أو عدة عناصر بالمصفوفة تعدّ المصفوفات أحد أدوات روبي المهمّة. وتمتلك المصفوفات بعض الدوال المفيدة للوصول إلى عنصر معيّن بها. للتعرف على بعض تلك الدوال سنقوم بإنشاء مصفوفة بقائمة المشتريات تحتوي على 5 عناصر. لنقم بإنشاء متغيّر باسم list وتعيين المصفوفة التي نريد إلى ذلك المتغيّر. list = %w(apples oranges milk bread sugar) للوصول إلى قيمة معيّنة في المصفوفة نكتب مكان وجود هذه القيمة في أقواس مربّعة، مكان تواجد القيمة يسمّى دليل index. إذًا إذا أردت أن أجد العنصر الموجود في المكان الأوّل من المصفوفة نكتب اسم المصفوفة، الأقواس المربّعة ورقم الدليل بداخلها هكذا: list[1] ولكن ماذا أعادت لنا روبي عند تنفيذ هذا؟ أعرف أنّك لم تتوقّع أن تعيد orangesبدلاً من apple. لماذا حدث ذلك لأنّ الترقيم في المصفوفات يبدأ من 0 وليس 1 فإذا أردنا الوصول إلى أوّل عنصر على الإطلاق في المصفوفة نكتب ذلك كالتالي: list[0] القيم السالبة يستخدم نظام الترقيم الخاص بالمصفوفات قيمًا سالبة أيضًا وذلك إذا أردنا بدء العدّ من آخر المصفوفة. إذًا إذا أردت الوصول إلى آخر عنصر في المصفوفة يمكنك استخدام -1. list[-1] هناك أيضًا دوال مدمجة جاهزة للوصول إلى أوّل وآخر عنصر في المصفوفة. list.first list.last دالة fetch يمكن استخدام دالّة fetch مع الدليل لإرجاع قيمة العنصر الموجود بهذا الدليل. list.fetch(2) # "milk" إذا تم كتابة معطى ثاني في الدّالّة ولا يوجد هناك العنصر الذي يشير إليه الدليل المحدّد فسيتمّ إرجاع القيمة الموجودة في المعطى الثّاني كقيمة افتراضيّة. مثال: list.fetch(20, "Not found") # "Not found" المصفوفة الجزئية يمكننا أيضًا إرجاع مصفوفة جزئيّة Subset Array من مصفوفة عن طريق كتابة معطى Parameter إضافي مع الدليل. يشير هذا المعطى إلى طول المصفوفة الجزئيّة التي نريد إرجاعها. إذًا إذا أردنا إرجاع أوّل ثلاثة عناصر في المصفوفة نكتب ذلك كالتالي: list[0, 3] # ["apples", "oranges", "milk"] طريقة أخرى لإرجاع مصفوفة جزئيّة هو استخدام مجال معيّن range. list[0..2] # ["apples", "oranges", "milk"] دالة include لمعرفة إذا كانت مصفوفة تحتوي على كائن معيّن نستخدم دالّة include والتي تستقبل معطى باسم الكائن الذي نريد التحقّق من وجوده. وحيث أنّ الدّالّة منطقية (بمعنى أنّها ترجع true أو false فقط) فإنّنا نكتب في نهايتها علامة استفهام، ?include. إذًا لو أردنا معرفة إذا كانت تحتوي مصفوفة list على سلسلة apples نكتب ذلك كالتالي: list.include?("apples") معرفة عدد عناصر المصفوفة إذا أردت معرفة كم عدد العناصر بالمصفوفة فيمكن استخدام دالّة size والتي تقوم بإرجاع عددًا صحيحًا يمثّل عدد العناصر الموجودة بالمصفوفة. list.size اسم آخر لدالّة size هو length. جرّب كتابة الأمر التالي ولاحظ كيف تمّ إرجاع نفس النتائج. list.length إضافة عناصر إلى المصفوفة دالة push ماذا لو أردنا إضافة شيء إلى المصفوفة؟ يمكننا إضافة سلسلة تحتوي على "cheese" إلى نهاية المصفوفة باستخدام دالّة push. تقوم الدّالّة بإلحاق السلسلة التي نريد إضافتها بنهاية المصفوفة. list.push("cheese") هناك عامل اختصار Shorthand Operator لفعل نفس الوظيفة وهي أقواس الزاوية المزدوجة Double Angle Brackets (<<). فمثلاً إذا أردنا إضافة سلسلة "juice" إلى مصفوفة list بطريقة أسرع نكتب ذلك هكذا: list << "juice" أسهل وأسرع بكثير من دالّة push أليس كذلك؟ والأمر اللّطيف أيضًا حول ذلك أن هذه الأسهم تشير إلى مصفوفة list كما لو كانت تخبر روبي بإضافة السلسلة إلى تلك المصفوفة. طريقة أخرى لإضافة عناصر إلى آخر المصفوفة هو استخدام معامل =+ والذي يعني أن تجعل المصفوفة تساوي نفسها (=) بالإضافة إلى (+) القيمة الموجودة في الطرف الأيمن. list += ["bananas", "cereals"] الشيفرة البرمجيّة أعلاه تطلب من روبي بأن تضيف السلسلتين "bananas" و"cereals" إلى نهاية المصفوفة list. دالة unshift إذا أردنا إضافة عنصر إلى بداية المصفوفة وليس نهايتها فيمكننا استخدام دالّة unshift والتي تعمل عمل push مع فرق أنّها تضيف العنصر إلى بداية المصفوفة. list.unshift("carrots") حذف عناصر من المصفوفة دالة pop يمكننا استخراج آخر عنصر من المصفوفة باستخدام دالّة pop. لنقل مثلاً أنّني قد غيّرت رأيي ولا أريد شراء العصير. يمكن إخراج العصير وهو العنصر الأخير في المصفوفة هكذا: list.pop كما تلاحظ لا نحتاج إلى معطيات لهذه الدّالّة فهي تقوم آليًّا بإخراج العنصر الأخير في المصفوفة. بعد تنفيذ الأمر في سطر أوامر روبي التفاعليّ ستلاحظ أنّ روبي قامت بإرجاع قيمة العنصر المحذوف ولم ترجع المصفوفة نفسها. هذه الميزة مفيدة إذا أردنا استخدام العنصر الأخير/المحذوف. لكن لا تستخدم هذه الدّالّة للوصول إلى آخر عنصر إذا لم تكن تريد حذفه فعلاً حيث أنّك لو تحقّقت من المصفوفة من جديد ستجد أنّ العنصر الأخير قد اختفى. دالة shift دالّة shift مشابهة لدالّة unshift والتي تضيف عنصر إلى بداية الدّالّة، الفرق الوحيد هو أنّ دالّة shift تقوم بإرجاع وحذف العنصر الأوّل من المصفوفة. أو بعبارة أخرى، هي تقوم بنفس عمل دالّة pop لكن على بداية المصفوفة. list.shift دالة drop يمكننا استخدام دالّة drop لحذف عدد من العناصر من مصفوفة معًا. المعطى الخاصّ بالدّالّة هو عدد العناصر المطلوب حذفها من بداية الدّالّة. list.drop(2) # تقوم بحذف عنصرين من بداية الدّالّة دالة !slice قد تتساءل ماذا لو أردت حذف عناصر ليست في بداية أو نهاية المصفوفة. يمكننا في هذه الحالة استخدام دالّة !slice. تأخذ دالّة !slice المعطى الأول هو رقم الدليل المطلوب البدء منها والمعطى الثّاني هو عدد العناصر المطلوب حذفها. list.slice!(0, 3) لاحظ أنّه في حال ما إذا لم نضف علامة التّعجّب في نهاية اسم الدّالة فإننا سنحصل على جزء من المصفوفة مثلما هو مُتوقّع، لكنّه لن يتم حذف العناصر من المصفوفة الأصلية دالة sort يمكننا ترتيب مصفوفة باستخدام دالّة sort. الأمر التالي سيؤدّي إلى ترتيب المصفوفة استنادًا إلى الحروف الأبجديّة: list.sort ستلاحظ أنّه تمّ إرجاع المصفوفة وعناصرها مرتّبة أبجديًّا. ولكن لم يغيّر ذلك شيئًا في ترتيب المصفوفة الأصلي، يمكنك التحقّق من ذلك بنفسك. فقط اكتب اسم المصفوفة واضغط Enter. ستجد أنّ المصفوفة الأصليّة لم تتغيّر. ولكن إذا أردت ترتيب المصفوفة وتغيير المصفوفة الأصليّة ماذا نفعل؟ يمكننا الآن الرجوع إلى دوال Bang التي تحدّثنا عنها في درس السلاسل والتي تقوم بتعديل القيمة الأصليّة للكائن ونستدعيها عن طريقة كتابة اسم الدالّة الأصليّة متبوعة بعلامة تعجّب. list.sort! دالة reverse يمكننا استخدام دالّة reverse من أجل طباعة المصفوفة معكوسة. هذه المصفوفة أيضًا لا تغيّر من قيمة المصفوفة الأصليّة للأبد، ولكن إن أردنا تغيير المصفوفة الأصليّة فلدينا دالّة reverse!. list.reverse دالة join دالّة أخيرة سنتعرّف عليها هي دالّة join. هذه الدّالّة مفيدة جدًّا لأنّه يمكن استخدامها لإنشاء سلسلة تقوم بدمج جميع عناصر مصفوفة معًا. تستقبل الدّالّة معطى يحتوي على الرّمز الذي تريد استخدامه كفاصل. مثلاً الأمر التالي: list.join(",") ماذا فعلنا هنا؟ لقد استدعينا دالّة join على مصفوفة list ومعطى الدّالّة هو سلسلة تحتوي على فاصلة والتي ستستخدم كفاصل بين عناصر المصفوفة. عند تنفيذ هذا الأمر ستطبع لك روبي على الشّاشة سلسلة تحتوي على جميع العناصر وبين كل عنصر والآخر الفاصلة التي أردنا استخدامها. خاتمة تعرّفنا في هذا الدّرس على أحد المفاهيم المهمّة في روبي وأيّ لغة برمجة عمومًا وهي المصفوفات. مع تعمّقك أكثر في تعلّم روبي ستلاحظ فوائد استخدام المصفوفات في شيفراتك البرمجيّة. تعرّفنا على الدوال الرئيسيّة المستخدمة مع المصفوفات ولكن إذا أردت معرفة معلومات أكثر عن ذلك يمكنك قراءة التوثيق الخاص بالمصفوفات في روبي.