المصفوفة array هي شكل من أشكال البيانات التي توفرها معظم لغات البرمجة والتي تسمح بتخزين عدة قيم تدعى عناصر معًا ضمن متغير واحد، ويمكن لهذه العناصر أن تكون من أنواع مختلفة من البيانات، مثل الأرقام والسلاسل النصية وغيرها من كائنات روبي. سنتعرف في هذا المقال على طرق إنشاء المصفوفات والوصول إلى القيم التي تحتويها، وإضافة وتعديل وحذف العناصر من المصفوفة، وطريقة المرور على عناصر المصفوفة، إذ تُعد المصفوفة في روبي كائنات مع توابعها الممكن استدعاؤها والاستفادة منها في التعامل مع عناصر المصفوفة.
إنشاء مصفوفة
في حال كان لدينا عدة قيم نحتاج التعامل معها ضمن البرنامج يمكننا تخزين كل منها في متغير خاص على النحو التالي:
shark1 = "Hammerhead" shark2 = "Great White" shark3 = "Tiger"
ولكن سنحتاج بتلك الطريقة لاختيار اسم متغير لكل قيمة منها، وفي حال كانت القيم كثيرة سيصبح الأمر صعبًا، وإذا أردنا إضافة قيمة جديدة إليها يجب تعريف متغير جديد وتذكُّر اسمه لاحقًا. هنا تأتي المصفوفات لحل تلك المشكلة عبر تخزين كل تلك القيم ضمن متغير واحد فقط. لإنشاء مصفوفة في روبي يمكن كتابة قيم العناصر ضمن أقواس معقوفة []
والفصل بينها بفواصل ,
على النحو التالي:
sharks = ["Hammerhead", "Great White", "Tiger"]
بدلًا من إنشاء ثلاثة متغيرات منفصلة أصبح لدينا الآن متغير واحد يحتوي على جميع القيم، ولإضافة قيمة جديدة للمصفوفة يمكن إضافتها مباشرةً دون الحاجة لإنشاء متغير جديد.
يمكن طباعة كامل المصفوفة باستخدام التابع print
، الذي سيعرض محتويات المصفوفة كما يلي:
print sharks
ليكون الخرج على النحو التالي:
["Hammerhead", "Great White", "Tiger"]
توفر لغة روبي طريقةً مختصرةً لإنشاء مصفوفة يكون فيها كل مُدخل هو كلمة واحدة، وذلك بكتابة الكلمات بين القوسين في الصيغة التالية {}w%
على النحو التالي:
days = %w{Monday Tuesday Wednesday Thursday Friday Saturday Sunday}
وسينتج عنها مصفوفة من الكلمات كما لو أننا عرفناها يدويًا ضمن أقواس معقوفة على النحو التالي:
days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
ونلاحظ عدم الحاجة لاستخدام علامات الاقتباس لتعريف تلك الكلمات ضمن الصيغة {}w%
، ولسنا مضطرين لتخزين عناصر من نفس النوع ضمن المصفوفة، ففي روبي يمكن للمصفوفات أن تحتوي على أي نوع من القيم بما في ذلك مصفوفات أخرى، وفيما يلي مثال على مصفوفة تحتوي على سلسلة نصية والقيمة nil
وعدد صحيح ومصفوفة من السلاسل النصية:
record = [ "Sammy", null, 7, [ "another", "array", ] ]
سنتعرف في الفقرة التالية على كيفية الوصول إلى البيانات المخزنة ضمن المصفوفات.
الوصول لعناصر المصفوفة
للوصول إلى عنصر محدد ضمن المصفوفة يمكننا الإشارة إلى رقم الفهرس لذلك العنصر، أي ترتيب موقعه ضمن المصفوفة، إذ تبدأ الفهارس في روبي ومعظم لغات البرمجة الأخرى من الرقم صفر، فمثلًا للوصول إلى العنصر الأول من المصفوفة يمكننا تمرير رقم الفهرس له بعد اسم المتغير وبين الأقواس المعقوفة:
sharks = ["Hammerhead", "Great White", "Tiger"]
تحتوي المصفوفة sharks
على ثلاثة عناصر، ورقم الفهرس لكل عنصر منها على النحو التالي:
2 | 1 | 0 |
---|---|---|
Tiger | Great White | Hammerhead |
العنصر الأول في المصفوفة وهو Hammerhead
له الفهرس رقم 0، أما العنصر الأخير في المصفوفة وهو Tiger
له الفهرس رقم 2، إذ وعلى عكس طريقة العد التقليدية التي تبدأ بالرقم 1، نلاحظ أن الفهارس تبدأ من الصفر، لذا يجب الاعتياد على ذلك عند التعامل مع المصفوفات لتجنب الأخطاء. يمكن معرفة عدد العناصر الموجودة في المصفوفة باستخدام التابع length
على النحو التالي:
sharks.length
ليكون الخرج على النحو التالي:
3
على الرغم من أن فهارس المصفوفة sharks
تبدأ من 0 وتنتهي بالفهرس 2، إلا أن تابع طول المصفوفة length
يعيد عدد العناصر الموجودة في المصفوفة والذي يساوي 3، ولا علاقة له برقم الفهرس للعناصر.
ملاحظة: يمكنك التفكير في الفهرس على أنه إزاحة offset، أي عدد الأماكن من بداية المصفوفة، إذ يكون العنصر الأول في المقدمة وبالتالي بدون إزاحة، أي سيكون الفهرس 0، أما العنصر الثاني فهو على بُعد عنصر واحد من بداية المصفوفة، لذلك ستكون إزاحته بمقدار 1 وقيمة الفهرس 1.
لمعرفة رقم الفهرس لعنصر محدد ضمن المصفوفة مثل العنصرTiger
يمكن استخدام التابع ()index
على النحو التالي:
print sharks.index("Tiger")
ليعطي الخرج التالي:
2
يعيد هذا التابع رقم الفهرس لأول عنصر من المصفوفة يحتوي على النص المحدد، وإذا لم يُعثر على عنصر مطابق لتلك القيمة فسيعيد التابع القيمة nil
:
print sharks.index("Whale")
سيكون هنا الخرج:
nil
للحصول على آخر عنصر من المصفوفة يمكن استخدام رقم الفهرس السالب 1-:
print sharks[-1]
وسيكون الخرج كما يلي:
"Tiger"
ويوجد أيضًا التابعين first
و last
في روبي للحصول على أول وآخر عنصر من المصفوفة دون الحاجة إلى استخدام رقم الفهرس لها:
puts sharks.first puts sharks.last
ويكون الخرج:
"Hammerhead" "Tiger"
وعند محاولة الوصول إلى فهرس غير موجود:
sharks[10]
سينتج عن ذلك القيمة nil
:
nil
يمكن أن تحتوي المصفوفات على مصفوفات أخرى ضمنها لينتج من ذلك مصفوفات متداخلة nested arrays يمكن الاستفادة من هذا الشكل من البيانات لتمثيل البيانات ثنائية الأبعاد في البرنامج، ويمكنك الاطلاع على مزيدٍ من المعلومات عن المصفوفات وأنواعها من خلال المقال المصفوفات Arrays في روبي، وفيما يلي مثال على مصفوفة متداخلة:
nested_array = [ [ "salmon", "halibut", ], [ "coral", "reef", ] ]
للوصول إلى العناصر الموجودة ضمن مصفوفة متداخلة يجب إضافة رقم فهرس إضافي يتوافق مع المصفوفة الداخلية، فمثلًا يمكن الوصول إلى القيمة coral
من المصفوفة السابقة كما يلي:
print nested_array[1][0];
ليكون الخرج على النحو التالي:
coral
نستخرج في هذا المثال العنصر الثاني أولًا من المصفوفة عبر رقم الفهرس 1 من المتغير nested_array
، وهو عنصر المصفوفة ["coral", "reef"]
، ثم نستخرج العنصر الأول من هذه المصفوفة عبر رقم الفهرس 0 لنحصل بذلك على القيمة المطلوبة "coral"
.
سنتعرف في الفقرة التالية على طريقة إضافة عناصر إلى المصفوفة.
إضافة عناصر إلى المصفوفات
لنعود إلى المصفوفة السابقة sharks
، التي تحتوي على ثلاثة عناصر تبدأ من رقم الفهرس 0 إلى 2:
sharks = ["Hammerhead", "Great White", "Tiger"]
لإضافة عنصر جديد إلى تلك المصفوفة، يمكن تعيين قيمة للفهرس الذي يلي آخر عنصر منها والذي في هذه الحالة هو 3 كما يلي:
sharks[3] = "Whale"; print sharks
ليكون الخرج على النحو التالي:
["Hammerhead", "Great White", "Tiger", "Whale"]
قد يؤدي استخدام هذه الطريقة إلى حدوث أخطاء، فإذا أضفنا عنصرًا إلى رقم فهرس ما أكبر من ذلك فسيؤدي ذلك لإضافة العنصر nil
داخل المصفوفة على النحو التالي:
sharks[5] = "Sand"; print sharks;
ويكون الخرج في هذه الحالة:
["Hammerhead", "Great White", "Tiger", "Whale", nil, "Sand"]
وعند محاولة الوصول إلى قيمة ذلك العنصر الزائد سنحصل على القيمة nil
:
sharks[4]
سيكون الخرج:
nil
يمكن استخدام التابع push
لتجنب هذه الأخطاء، إذ يضيف هذا التابع عنصرًا إلى نهاية المصفوفة دون مشاكل:
sharks.push("Thresher") print sharks
وعندها سيكون الخرج:
["Hammerhead", "Great White", "Tiger", "Whale", nil, "Whale", "Thresher"]
يمكن أيضًا استخدام الصيغة >>
بدلًا من التابع push
لإضافة عنصر إلى نهاية المصفوفة كما يلي:
sharks << "Bullhead"
ويكون الخرج:
["Hammerhead", "Great White", "Tiger", "Whale", nil, "Whale", "Thresher", "Bullhead"]
نستخدم التابع ()unshift
لإضافة عنصر إلى بداية المصفوفة كما يلي:
sharks.unshift("Angel") print sharks
ليعطي الخرج التالي:
["Angel", "Hammerhead", "Great White", "Tiger", "Whale", nil, "Whale", "Thresher", "Bullhead"]
سنتعرف في الفقرة التالية على طريقة إزالة عناصر من المصفوفة.
إزالة العناصر من المصفوفات
يمكن استخدام التابع delete
أو delete_at
لإزالة عنصر محدد من المصفوفة. لنختبر ذلك بإزالة العنصر الفارغ داخلها والذي أنشأناه عن طريق الخطأ، ونبدأ بالعثور على موضعه في المصفوفة باستخدام التابع index
على النحو التالي:
print sharks.index(nil)
والذي يعطينا الخرج التالي:
4
ثم نستخدم التابع delete_at
لإزالة ذلك صاحب الفهرس رقم 4 ونطبع المصفوفة لنتأكد:
sharks.delete_at(4) print sharks
سيكون الخرج على النحو التالي:
["Angel", "Hammerhead", "Great White", "Tiger", "Whale", "Thresher", "Bullhead"]
يزيل التابع delete
العناصر التي تتطابق مع القيمة التي تُمرّر له. لنختبر استخدامه بإزالة العنصر Whale
من المصفوفة السابقة كما يلي:
sharks.delete("Whale") print sharks;
ويكون الخرج في هذه الحالة:
["Angel", "Hammerhead", "Great White", "Tiger", "Thresher", "Bullhead"]
يزيل التابع delete
جميع القيم المطابقة للقيمة التي نمررها له، لذا إذا كانت المصفوفة تحتوي على عناصر مكررة فستُزال جميعها، وبالمقابل يتيح التابع pop
إزالة آخر عنصر من المصفوفة:
sharks.pop print sharks;
ليكون الخرج كما يلي:
["Angel", "Hammerhead", "Great White", "Tiger", "Thresher"]
نلاحظ إزالة العنصر Bullhead
، وهو آخر عنصر في المصفوفة. لإزالة أول عنصر من المصفوفة يمكن استخدام التابع shift
على النحو التالي:
sharks.shift print sharks
ليكون الخرج:
["Hammerhead", "Great White", "Tiger", "Thresher"]
نلاحظ إزالة العنصر Angel
من بداية المصفوفة، ويمكن استخدام التابعين pop
و shift
لإزالة العناصر من بداية ونهاية المصفوفة كما لاحظنا، ويفضل استخدام التابع pop
عند الحاجة لأن حذف العنصر من نهاية المصفوفة لن يؤثر على رقم الفهرس لباقي العناصر.
تعدل كلًا من التوابع delete_at
و pop
و shift
على قيمة المصفوفة الأصلية وتعيد العنصر المحذوف:
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"] deleted_at_element = sharks.delete_at(1) popped_element = sharks.pop puts "Deleted_at element: #{deleted_at_element}" puts "Popped element: #{popped_element}" puts "Remaining array: #{sharks}"
وسيكون الخرج:
Deleted_at element: Great White Popped element: Whale Remaining array: ["Hammerhead", "Tiger"]
بعد أن تعرفنا على طرق إزالة العناصر من المصفوفة، سنتعرف في الفقرة التالية على طريقة التعديل على قيمة عنصر من المصفوفة.
تعديل عناصر موجودة في المصفوفات
يمكن تحديث قيمة عنصر من المصفوفة عن طريق تعيين قيمة جديدة لفهرس ذلك العنصر باستخدام معامل الإسناد تمامًا كما نُعرف المتغيرات العادية. تحتوي المصفوفة التالية على العنصر "Hammerhead"
في الفهرس رقم 0، لنحاول تعديل قيمة ذلك العنصر إلى القيمة "Angel"
:
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"] sharks[0] = "Angel" print sharks;
سيكون الخرج على النحو التالي:
["Angel", "Great White", "Tiger", "Whale"]
يمكن التأكد من تعديل قيمة ذلك العنصر بالبحث عن القيمة الجديدة باستخدام التابع index
لنلاحظ أن القيمة الجديدة موجودة في نفس المكان. سنتعرف في الفقرة التالية على طريقة المرور على عناصر المصفوفة.
المرور على عناصر المصفوفة
توفر لغة روبي العديد من الطرق للمرور على عناصر المصفوفة، ويختلف التابع المُستخدم بحسب الهدف الذي نريده. لنبدأ بالمرور على عناصر المصفوفة وطباعة قيمة كل منها وذلك باستخدام الصيغةfor..in
على النحو التالي:
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"] for shark in sharks do puts shark end
تعيّن روبي قيمة كل عنصر في المتغير المحلي shark
، ويمكنك بعد ذلك طباعة قيمة ذلك العنصر باستخدام التابع puts
. على الرغم من إمكانية استخدام الحلقة التكرارية for..in
للمرور على عناصر المصفوفة، إلا أن المصفوفات في لغة روبي هي كائنات ويتوفر ضمنها التابع each
، الذي يعمل بنفس طريقة الحلقة التكرارية for..in
ولكن بصيغة مختلفة:
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"] sharks.each do |shark| puts shark end
يستخدم التابع each
صيغةً تتكرر كثيرًا في لغة روبي، إذ يأخذ التابع كتلة block مثل وسيط، ويُقصد بالكتلة هنا شيفرة برمجية ستنفذ لاحقًا في سياق التابع. ستُنفذ في مثالنا السابق العبارة البرمجية puts shark
، أما الكلمة shark
المحاطة بعلامات الأنبوب |
هي المتغير المحلي الذي يمثل العنصر الحالي في المصفوفة، إذ تسنِد لغة روبي قيمة العنصر الحالي إلى هذا المتغير وتنفذ بعدها التعبير الموجود ضمن الكتلة، ويكرّر التابع each
هذه العملية لكل عنصر من عناصر المصفوفة، ويكون الخرج على النحو التالي:
Hammerhead Great White Tiger Whale
يمكن استخدام الصيغة المختصرة ضمن الأقواس المعقوصة curly braces {}
بدلًا من كلمتي do
و end
إذا كانت الكتلة مكونةً من سطر برمجي واحد فقط:
... sharks.each {|shark| puts shark }
وسينتج عنها نفس الخرج السابق.
يعمل التابع each_with_index
بنفس طريقة التابع each
، ولكنه يتيح الوصول إلى رقم الفهرس للعنصر الحالي في المصفوفة. لنختبر ذلك بطباعة رقم الفهرس والقيمة لكل عنصر من المصفوفة:
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"] sharks.each_with_index do |shark, index| puts "The index is #{index}" puts "The value is #{shark}" end
تسند روبي قيمة كل عنصر في المصفوفة إلى المتغير shark
، وتسند رقم الفهرس الحالي إلى المتغير index
في كل مرة، ويمكن بعد ذلك الإشارة إلى هذين المتغيرين داخل الكتلة بحيث يمكن الوصول إلى قيمة العنصر الحالي ورقم فهرسه في المصفوفة.
The index is 0 The value is Hammerhead The index is 1 The value is Great White The index is 2 The value is Tiger The index is 3 The value is Whale
تعلمنا في هذه الفقرة عدة طرق للمرور على عناصر المصفوفة، وهي من أكثر المهمات التي نحتاجها عند التعامل مع المصفوفات.
الخاتمة
المصفوفات في روبي ومعظم لغات البرمجة من المفاهيم المهمة والقوية والتي يجب التعرف عليها وطرق التعامل معها. تعرّفنا في هذا المقال على المصفوفات وكل المهمات الأساسية للتعامل معها من إنشاء المصفوفات والوصول إلى عناصرها وإضافة وإزالة وتعديل العناصر ضمن المصفوفة، وتعرفنا على طريقتين للمرور على عناصر المصفوفة وعرض محتوياتها.
لمزيد من التفصيل، ارجع إلى صفحة النوع Array في موسوعة حسوب.
ترجمة -وبتصرف- للمقال How To Work with Arrays in Ruby لصاحبيه Brian Hogan و Tony Tran.
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.