تسمح المصفوفات arrays بتمثيل قائمة من البيانات معًا وتخزينها ضمن متغير واحد لنتمكن من إجراء العمليات المختلفة على تلك البيانات، مثل فرزها أو إزالة العناصر المكررة منها، أو عكس ترتيبها، أو استخراج أجزاء من المصفوفة، أو البحث ضمنها عن بيانات محددة، ويمكننا أيضًا تحويل المصفوفة إلى سلسلة نصية أو إلى مصفوفة بيانات أخرى أو دمج عناصر المصفوفة معًا في قيمة واحدة. سنتعرف في هذا المقال على بعض التوابع التي توفرها لغة روبي للتعامل مع البيانات ضمن المصفوفات. سنلاحظ انتهاء أسماء بعض تلك التوابع بعلامة تعجب !
، مما يشير أن هذا التابع سيعدل على قيمة المصفوفة الأصلية وقد يرمي استثناءات، ويوجد غالبًا تابع مقابل بنفس الاسم لمعظم التوابع الموجودة ضمن المصفوفات ولكن ينتهي بهذه اللاحقة. يوجد كذلك توابع أخرى تنتهي بعلامة استفهام ?
وهي توابع تعيد قيمة بوليانية منطقية تشير، ويُعد هذا الأسلوب شائعًا في تسمية التوابع ضمن روبي، وسنبدأ بالتعرف على توابع المصفوفات بدايةً من خلال عدة طرق للوصول إلى العناصر ضمن المصفوفة.
الوصول إلى عنصر من المصفوفة
تعرفنا في المقال السابق على طريقة الوصول لعنصر محدد ضمن المصفوفة باستخدام رقم الفهرس الخاص به والذي يبدأ من الصفر على النحو التالي:
sharks = ["Tiger", "Great White", "Hammerhead", "Angel"] sharks[0] # "Tiger" sharks[1] # "Great White" sharks[-1] # "Angel"
وتعرفنا أيضًا على كل من التابعين first
و last
واللذان يمكن استخدامهما للحصول على أول وآخر عنصر من المصفوفة:
sharks = ["Tiger", "Great White", "Hammerhead", "Angel"] sharks.first # "Tiger" sharks.last # "Angel"
وعند الوصول لعنصر غير موجود ضمن المصفوفة، سنحصل على القيمة nil
، وإذا أردنا أن ينتج عن تلك العملية خطأ فيمكن استخدام التابع fetch
:
sharks.fetch(42)
ليكون الخرج على النحو التالي:
IndexError: index 42 outside of array bounds: -4...4
ويمكن تحديد قيمة افتراضية للعناصر غير الموجودة بدلًا من رمي خطأ، مثل تمرير تلك القيمة الافتراضية مثل وسيط ثانٍ للتابع fetch
:
sharks.fetch(42, "Nope") # "Nope"
سنتعرف في الفقرة التالية على طريقة الحصول على عدة عناصر من المصفوفة معًا.
استخراج عدة عناصر من المصفوفة
قد نحتاج أحيانًا للحصول على عدة عناصر من المصفوفة معًا بدلًا من عنصر واحد فقط، ويمكننا ذلك عبر تحديد رقم الفهرس لأول عنصر نريده من المصفوفة، ثم تمرير عدد العناصر التي نريد استخراجها بدءًا من ذلك العنصر، لتُنشأ مصفوفةٌ جديدةٌ تحتوي على تلك العناصر المحددة، فمثلًا يمكن استخراج العنصرين المتوسطين من المصفوفة sharks
على النحو التالي:
sharks = ["Tiger", "Great White", "Hammerhead", "Angel"] sharks[1,2] # ["Great White", "Hammerhead"]
نبدأ من الفهرس رقم 1 الذي يحتوي على قيمة "Great White"
ونحدد بعدها عدد العناصر التي نريد استخراجها وهو 2، وبذلك تُنشأ مصفوفة جديدة تحتوي على "Great White"
و "Hammerhead"
. يمكن استخدام التابع slice
لإجراء نفس العملية:
sharks = ["Tiger", "Great White", "Hammerhead", "Angel"] sharks.slice(1,2) # ["Great White", "Hammerhead"]
يعيد التابع slice
مصفوفةً جديدةً دون التعديل على المصفوفة الأصلية، ولكن إذا استخدمنا التابع !slice
ستتغير قيمة المصفوفة الأصلية. يمكن أيضًا استخدام التابع take
لاستخراج عدد محدد من العناصر بدءًا من بداية المصفوفة:
sharks = ["Tiger", "Great White", "Hammerhead", "Angel"] sharks.take(2) # ["Tiger", "Great White"]
قد نحتاج لاستخراج عنصر عشوائي من المصفوفة بدلًا من قيمة محددة، وسنتعرف على طريقة تنفيذ ذلك في الفقرة التالية.
الحصول على عنصر عشوائي من المصفوفة
قد نحتاج في بعض الحالات لاستخراج قيمة عشوائية لا على التعيين من مصفوفة ما، خصوصًا عند تطوير بعض الألعاب التي تعتمد على الحظ، إذ يمكننا تنفيذ ذلك بتخزين جميع الخيارات الممكنة ضمن مصفوفة واختيار إحداها بتوليد رقم فهرس عشوائي بين الرقم 0 ورقم آخر فهرس لآخر عنصر من المصفوفة. تتيح لك روبي طريقةً أسهل عبر التابع sample
، الذي يعيد عنصرًا عشوائيًا من المصفوفة مباشرةً على النحو التالي:
answers = ["Yes", "No", "Maybe", "Ask again later"] print answers.sample
ويكون الخرج:
Maybe
يقبل التابع sample
عددًا مثل وسيط أول، ويعيد مصفوفةً تحتوي على عدد محدد من العناصر العشوائية، فإذا كنا بحاجة لأكثر من عنصر عشوائي، يمكننا تمرير العدد المطلوب لذلك التابع كما يلي:
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"] sample = sharks.sample(2) print sample
ليكون الخرج على النحو التالي:
["Whale", "Great White"]
سنتعرف في الفقرة التالية على طرق البحث عن عناصر محددة داخل مصفوفة.
البحث وتصفية عناصر المصفوفة
يمكننا البحث عن عناصر محددة داخل مصفوفة بالمرور على عناصر تلك المصفوفة واحدًا تلو الآخر وفحص كل عنصر منها إلى أن نجد العنصر المطلوب، ولكن روبي توفر عدة توابع تُسهل عملية البحث تلك ضمن المصفوفات، إذ يمكن مثلًا التحقق ما إذا كان العنصر موجودًا ضمن المصفوفة باستخدام التابع ?include
، الذي يعيد القيمة true
في حال كان العنصر المحدد موجودًا:
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"] sharks.include? "Tiger" # true ["a", "b", "c"].include? 2 # false
إذ يبحث التابع ضمن المصفوفة عن العنصر الذي يطابق القيمة المُمررة له تمامًا، أي لا يمكننا مثلًا البحث عن أجزاء من سلسلة نصية على النحو التالي:
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"] sharks.include? "Tiger" # true sharks.include? "tiger" # false sharks.include? "ti" # false
يمكن حل المشكلة باستخدام التابع find
، الذي يعيد أول عنصر يطابق الشرط المحدد داخل المصفوفة، فمثلًا للبحث عن أول عنصر يحتوي على الحرف a
ضمن مصفوفة sharks
، يمكن استخدام التابع each
للمرور على كل عنصر بالترتيب والتوقف عند العثور على العنصر الأول المطابق لهذا الشرط كما يلي:
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"] result = nil sharks.each do |shark| if sharks.include? "a" result = shark break end end
أو استخدام التابع find
بدلًا من ذلك لتنفيذ نفس العملية:
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"] result = sharks.find {|item| item.include?("a")} print result
ويكون الخرج:
Hammerhead
ينفذ التابع find
التعبير البرمجي الممرر له على كل عنصر داخل المصفوفة، وفي حال كانت القيمة التي يعيدها ذلك التعبير البرمجي الممرر القيمة true
، يوقف التابع find
عملية المرور ويعيد تلك القيمة مباشرةً، وإذا لم يُعثر على أي عنصر يطابق الشرط المحدد يعيد القيمة nil
. يعمل التابع select
بطريقة مشابهة للتابع find
ولكنه سيُنشئ مصفوفة جديدة تحتوي على جميع العناصر التي تطابق الشرط المحدد بدلًا من قيمة واحدة فقط على النحو التالي:
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"] results = sharks.select {|item| item.include?("a")} print results
وتكون النتيجة على النحو التالي:
["Hammerhead", "Great White", "Whale"]
يعيد التابع reject
مصفوفةً جديدةً تحتوي على العناصر التي لا تطابق الشرط المحدد، ويمكن استخدامه لتصفية وإزالة العناصر التي لا نرغب بها من المصفوفة، فمثلًا يمكننا إزالة جميع العناصر التي تحتوي على الحرف a
من المصفوفة كما يلي:
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"] results = sharks.reject {|item| item.include?("a")} print results
ويكون الخرج:
["Tiger"]
يعيد كلًا من التابعين select
و reject
مصفوفةً جديدةً دون تغيير قيمة المصفوفة الأصلية، ويمكن استخدام التابعين المقابلين !select
و !reject
في حال أردنا التعديل على قيمة المصفوفة الأصلية؛ أما التابع find_all
فهو بديل للتابع select
ولكن الفرق بأنه لا يوجد تابع مقابل له للتعديل على قيمة المصفوفة. سنتعرف في الفقرة التالية على طرق ترتيب عناصر المصفوفة.
ترتيب عناصر المصفوفة
نحتاج في كثير من الأحيان لترتيب بعض البيانات، مثل ترتيب قائمة من الأسماء أبجديًا، أو ترتيب بعض الأرقام من الأصغر إلى الأكبر، ومن التوابع التي تتعامل مع ترتيب العناصر ضمن المصفوفة هو التابع reverse
، الذي يعكس ترتيب العناصر؛ فإذا كانت لدينا قائمة مرتبة من بيانات يمكن استخدام ذلك التابع بمثابة طريقة سريعة لعكس ترتيبها على النحو التالي:
sharks = ["Angel", "Great White", "Hammerhead", "Tiger"] reversed_sharks = sharks.reverse print reversed_sharks
ويكون الخرج:
["Tiger", "Hammerhead", "Great White", "Angel"]
يعيد التابع reverse
مصفوفةً جديدةً دون تغيير قيمة المصفوفة الأصلية، ويمكن استخدام التابع !reverse
في حال أردنا تغيير قيمة المصفوفة الأصلية. لا يكفي عكس ترتيب عناصر المصفوفة، إذ نحتاج معظم الأحيان لترتيب عناصر غير مرتبة، ويمكن لذلك استخدام التابع sort
لترتيب العناصر ضمن المصفوفة بأي طريقة نريدها، فإذا كانت العناصر ضمن المصفوفة قيم بسيطة مثل السلاسل النصية أو الأرقام، فسيرتب التابع sort
تلك العناصر مباشرةً:
sharks = ["Tiger", "Great White", "Hammerhead", "Angel"] sorted_sharks = sharks.sort print sorted_sharks
ويعطي الخرج التالي:
["Angel", "Great White", "Hammerhead", "Tiger"]
لترتيب البيانات بطريقة مختلفة يجب أن نخبر التابع sort
بطريقة فعل ذلك، إذ يمكن تمرير كتلة برمجية للتابع sort
الذي سيمرِّر لها عناصر المصفوفة لمقارنتها ويمكن ذلك باستخدام معامل المقارنة <=>
، إليك مثالًا عن ذلك:
1 <=> 2 # -1 2 <=> 2 # 0 2 <=> 1 # 1
يقبل التابع sort
في لغة روبي كتلةً برمجيةً يجب أن تعيد إحدى القيم 1- أو 0 أو 1 للتعبير عما إذا كان العنصر الأول يسبق أو يساوي أو يلي العنصر الثاني بالترتيب، وبناءً على تلك المقارنة تُرتب عناصر المصفوفة، وفي ما يلي مقارنة لقيم عناصر المصفوفة وترتيبها تصاعديًا:
sharks = ["Tiger", "Great White", "Hammerhead", "Angel"] sorted_sharks = sharks.sort{|a,b| a <=> b } print sorted_sharks
يُمثل المتغيران a
و b
عنصرين من المصفوفة يُقارن بينهما حاليًا، ونتيجة ترتيب المصفوفة هي:
["Angel", "Great White", "Hammerhead", "Tiger"]
يمكن عكس ترتيب العناصر ضمن عبارة المقارنة بينهما لترتيب العناصر بترتيب عكسي على النحو التالي:
sharks = ["Tiger", "Great White", "Hammerhead", "Angel"] sorted_sharks = sharks.sort{|a,b| b <=> a } print sorted_sharks
ليكون الخرج:
["Tiger", "Hammerhead", "Great White", "Angel"]
كما لاحظنا، يمكن باستخدام التابع sort
ترتيب المصفوفات التي تحتوي على أنواع بسيطة من البيانات، مثل الأعداد الصحيحة، أو العشرية، أو السلاسل النصية، ولكن عندما تحتوي المصفوفة على كائنات أكثر تعقيدًا، سيكون عليك فعل المزيد.
يوضح المثال التالي مصفوفة من قيم من نوع hash، وكل hash يمثّل سمك قرش shark:
sharks = [ {name: "Hammerhead"}, {name: "Great white"}, {name: "Angel"} ]
سيفشل ترتيبها مباشرةً باستخدام sort
:
sharks.sort
وعند استدعائه على تلك المصفوفة تظهر الرسالة التالية:
ArgumentError: comparison of Hash with Hash failed
ولمقارنة تلك القيم يجب أن نخبر التابع sort
بطريقة المقارنة بينها. لنرتب تلك الكائنات أبجديًا بحسب خاصية الاسمname:
ضمنها على النحو التالي:
sorted_sharks.sort{|a, b| a[:name] <=> b[:name]} print sorted_sharks
ليكون الخرج:
[{:name=>"Angel"}, {:name=>"Great white"}, {:name=>"Hammerhead"}]
يمكن عند ترتيب مصفوفة من الكائنات استخدام التابع sort_by
بدلًا من sort
، الذي يستخدم خوارزمية أكثر كفاءة في الترتيب، ويقبل التابع sort_by
كتلة برمجية يُمرر إليها وسيط واحد فقط وهو العنصر الحالي في المصفوفة:
sharks = [ {name: "Hammerhead"}, {name: "Great white"}, {name: "Angel"} ] sorted_sharks = sharks.sort_by{|shark| shark[:name] } print sorted_sharks
يكون الخرج هنا:
[{:name=>"Angel"}, {:name=>"Great white"}, {:name=>"Hammerhead"}]
يُطبق التابع sort_by
خوارزمية ترتيب تدعى تحويل شوارتزيان Schwartzian transform، التي تُستخدم لمقارنة الكائنات بناءً على قيمة محددة منها، وهي خوارزمية أكثر كفاءة من خوارزمية الترتيب ضمن التابع sort
؛ إذ يعيد كلًا من التابعين sort
و sort_by
مصفوفات جديدة دون تغيير قيمة المصفوفة الأصلية، وللتعديل على قيمة المصفوفة الأصلية نستخدم التابعين المقابلين لهما!sort
و !sort_by
، وقد نحتاج أحيانًا لحذف العناصر المكررة ضمن المصفوفة، وهذا ما سنتعرف عليه في الفقرة التالية.
إزالة العناصر المكررة من المصفوفة
قد تحتوي المصفوفات على بعض العناصر المكررة ضمنها، ولإزالة ذلك التكرار يمكن المرور على المصفوفة وإزالة التكرار منها يدويًا، أو يمكن استخدام التابع uniq
، الذي يعيد مصفوفةً جديدةً تحتوي قيم المصفوفة نفسها ولكن دون التكرار:
[1,2,3,4,1,5,3].uniq # [1,2,3,4,5]
سنحاول في المثال التالي دمج مجموعتين من البيانات وسنعالج مشكلة تكرار بعض العناصر في المصفوفة الناتجة:
sharks = ["Tiger", "Great White"] new_sharks = ["Tiger", "Hammerhead"]
يمكن الدمج بينها باستخدام معامل الجمع +
لنحصل على عنصر مكرر في المصفوفة الناتجة:
sharks + new_sharks # ["Tiger", "Great White", "Tiger", "Hammerhead"]
يمكن استخدام التابع uniq
لإزالة التكرار في المصفوفة الناتجة، ولكن بدلًا من ذلك يمكن تجنب ذلك التكرار من الأساس باستخدام معامل الأنبوب |
الذي يدمج المصفوفتين دون تكرار العناصر المشتركة بينهما بدلًا من معامل الجمع +
وذلك على النحو التالي:
sharks | new_sharks # ["Tiger", "Great White", "Hammerhead"]
يمكن في روبي طرح المصفوفات من بعضها باستخدام معامل الطرح -
للحصول على القيم غير المكررة فقط بين كلا المصفوفتين كما يلي:
sharks = ["Tiger", "Great White"] new_sharks = ["Tiger", "Hammerhead"] sharks - new_sharks # ["Great White"]
سنتعرف في الفقرة التالية على طرق التعديل على عناصر المصفوفة.
تعديل عناصر المصفوفة
يمكن استخدام التابع map
أو التسمية البديلة له collect
لتحويل محتويات المصفوفة بتطبيق عملية ما على كل عنصر في المصفوفة، فمثلًا يمكن تنفيذ عمليات حسابية على كل عنصر في المصفوفة وإنشاء مصفوفة جديدة تحتوي على قيمة تلك العملية الحسابية لكل عنصر منها:
numbers = [2,4,6,8] # square each number squared_numbers = numbers.map {|number| number * number} print squared_numbers
المتغير squared_numbers
هو مصفوفة تحتوي على قيمة مربع كل عدد من المصفوفة الأصلية:
[4, 16, 36, 64]
يُستخدم التابع map
غالبًا في تطبيقات الويب لتحويل عناصر من المصفوفة إلى عناصر HTML لعرضها ضمن قائمة منسدلة في الصفحة على النحو التالي:
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"] options = sharks.map {|shark| "<option>#{shark}</option>"} print options
تحتوي المصفوفة الجديدة options
على كل عنصر من المصفوفة الأصلية محاطًا بالوسم <option></option>
:
["<option>Hammerhead</option>", "<option>Great White</option>", "<option>Tiger</option>", "<option>Whale</option>"]
يعيد التابع map
مصفوفةً بالقيم الجديدة دون التعديل على المصفوفة الأصلية، ويمكن باستخدام التابع !map
تعديل قيمة المصفوفة الأصلية، ويمكن استخدام التسمية البديلة للتابع collect
بنفس الطريقة، ويُفضّل اعتماد أحد هذين التابعين لتوحيد الاستخدام ضمن الشيفرة البرمجية، وبما أن التابع map
يعيد مصفوفةً جديدة فيمكن تحويل أو تعديل عناصر تلك المصفوفة الجديدة مجددًا أو تحويلها مثلًا إلى سلسلة نصية، وسنتعرف على ذلك في الفقرة التالية.
تحويل المصفوفة إلى سلسلة نصية
تحتوي جميع الكائنات في لغة روبي على التابع to_s
والذي يحوّل أي كائن إلى سلسلة نصية، وهذا ما يستخدمه التابع print
داخليًا لطباعة الكائنات المٌمررة له على الشاشة. لنختبر ذلك على المصفوفة التالية:
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
ينتج عن استدعاء التابع to_s
على تلك المصفوفة السلسلة النصية التالية:
"[\"Hammerhead\", \"Great White\", \"Tiger\", \"Whale\"]"
قد تفيدنا تلك العملية في معاينة قيم المتغيرات أثناء تطوير البرامج.
يوجد أيضًا التابع join
، الذي يحوّل المصفوفة إلى سلسلة نصية بطريقة أخرى عبر دمج تلك العناصر بجانب بعضها بعضًا، ويقبل وسيطًا هو سلسلة نصية ستفصل بين تلك العناصر مثل المسافة الفارغة. لنختبر ذلك بتحويل المصفوفة السابقة إلى سلسلة نصية على النحو التالي:
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"] result = sharks.join(" ") print result
لتكون النتيجة:
Hammerhead Great White Tiger Whale
يمكن بدلًا من المسافة الفارغة فصل القيم بفاصلة ومسافة بين العناصر بتمريرها للتابع كما يلي:
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"] result = sharks.join(", ") print result
ويكون الخرج في هذه الحالة:
Hammerhead, Great White, Tiger, Whale
وإذا لم نمرر أي وسيط للتابع join
، سيعيد سلسلةً نصيةً تحتوي على العناصر الموجودة في المصفوفة دون فواصل بينها:
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"] result = sharks.join print result
وتكون النتيجة على النحو التالي:
HammerheadGreat WhiteTigerWhale
يمكن استخدام التابع join
مع التابع map
لتحويل مصفوفة من البيانات إلى نتيجة يمكن عرضها على الشاشة، إذ يحوّل التابع map
كل عنصر من المصفوفة إلى الشكل الجديد، ثم يدمج التابع join
تلك القيم في سلسلة نصية يمكن طباعتها على الشاشة، إذ يمكننا مثلًا تحويل العناصر إلى عناصر HTML كما فعلنا سابقًا ثم دمجها باستخدام التابع join
في سلسلة نصية يفصل بينها أسطر جديدة:
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"] options = sharks.map {|shark| "<option>#{shark}</option>"} output = options.join("\n") print output
ليعطي الخرج التالي:
<option>Hammerhead</option> <option>Great White</option> <option>Tiger</option> <option>Whale</option>
أحيانًا نحتاج لحساب قيمة إجمالية من عناصر المصفوفة أو تنفيذ عملية ما عليها ينتج منها قيمة واحدة، وسنتعرف على طريقة ذلك في الفقرة التالية.
تقليص المصفوفة إلى قيمة واحدة
يمكن حساب قيمة معينة من عناصر المصفوفة بالمرور على كل عنصر منها باستخدام التابع each
ودمجه في النتيجة النهائية، مثل حساب المجموع الكلي للأرقام ضمن المصفوفة على النحو التالي:
result = 0 [1, 2, 3].each {|num| result += num} print result
سيكون الخرج:
6
يمكننا بدلًا من ذلك استخدام التابع reduce
، الذي يُنفذ عمليةً معينة على كل عنصر من عناصر المصفوفة مع تمرير قيمة الدمج الحالية مع العنصر الحالي إلى الكتلة البرمجية المٌمررة له، إذ يقبل التابع reduce
وسيطًا وهو القيمة الابتدائية للنتيجة ويستخدم الكتلة البرمجة المُمررة له والتي سيُمرر لها متغيرين هما قيمة الدمج الحالية والعنصر الحالي، ويمكن داخل الكتلة البرمجية تحديد طريقة إضافة العنصر الحالي إلى النتيجة النهائية، فمثلًا لجمع عناصر المصفوفة يمكن تمرير القيمة 0 مثل قيمة ابتدائية للنتيجة ثم إضافة قيمة كل عنصر من المصفوفة إلى النتيجة المُمررة داخل الكتلة البرمجية على النحو التالي:
output = [1,2,3].reduce(0) {|result, current| result += current } print output
لتكون النتيجة في الخرج:
6
وفي حال كانت النتيجة الابتدائية هي صفر 0، يمكننا اختصار تمريرها مثل وسيط للتابع وتمرير الكتلة البرمجية له فقط، إذ ستكون القيمة الابتدائية هي قيمة أول عنصر من المصفوفة:
output = [1,2,3].reduce {|result, current| result += current } print output
ويكون الخرج:
6
يمكن تحديد تابع ثنائي binary أو تابع عادي على كائن واحد يقبل كائنًا آخر مثل وسيط له ليٌستدعى على كل عنصر من عناصر المصفوفة، ويستخدم التابع reduce
نتيجة ذلك الاستدعاء لإنشاء قيمة واحدة تدل على النتيجة النهائية، وعند جمع عددين مثلًا 2 + 2
في روبي، يٌفهم ذلك على أنه استدعاء لتابع الجمع +
على كائن العدد 2 كما يلي:
2.+(2) # 4
يمكن استخدام الصيغة 2 + 2
في روبي لتسهيل القراءة لتلك العبارة البرمجية، وينتج عنها داخليًا في اللغة استدعاء لتابع الجمع +
على العدد 2، وبما أن التابع reduce
يسمح بتحديد تابع ثنائي لاستدعائه على كل عنصر من عناصر المصفوفة مع النتيجة، فيمكن تمرير اسمه على شكل رمز، مثل تمرير الرمز +:
للتابع reduce
مثلًا لاستدعاء تابع الجمع على كل عنصر لجمع عناصر المصفوفة:
output = [1, 2, 3].reduce(:+) print output
لتكون النتيجة في الخرج:
6
يمكن استخدام التابع reduce
لتنفيذ العديد من العمليات على عناصر المصفوفة، إذ يمكن استخدامه لتحويل تلك القيم، كما يمكن استخدامه لتقليص قيم المصفوفة للحصول على قيمة مفردة، ولكن لا توجد قاعدة تنص على أن القيمة المفردة ليست بمصفوفة جديدة.
إذا كان لدينا قائمة من القيم التي نريد تحويلها إلى أعداد صحيحة، ولكن نريد فقط اختيار القيم التي يمكن تحويلها إلى أعداد صحيحة، فيمكن استخدام التابع reject
لإزالة القيم غير العددية، ثم استخدام التابع map
لتحويل القيم المتبقية إلى أعداد صحيحة، أو يمكن فعل كل ذلك في خطوة واحدة باستخدام التابع reduce
باستخدام مصفوفة فارغة مثل قيمة ابتدائية ثم نحول القيمة الحالية إلى عدد صحيح باستخدام التابع Integer
في الكتلة البرمجية المُمررة، وإذا كانت القيمة غير قابلة للتحويل إلى عدد صحيح سيرمي التابع Integer
استثناء يمكننا التقاطه وتبديل القيمة الحالية بالقيمة nil
، ثم إضافة القيمة الحالية إلى مصفوفة النتيجة فقط إذا لم تكن nil
على النحو التالي:
values = ["1", "2", "a", "3"] integers = values.reduce([]) do |array, current| val = Integer(current) rescue nil array.push(val) unless val.nil? array end print integers
سيكون الخرج:
[1,2,3]
كما لاحظنا، يُستخدم التابع reduce
في حال كانت النتيجة النهائية من المصفوفة قيمة مفردة أو مصفوفة جديدة بطول مختلف عن المصفوفة الأصلية.
الخاتمة
تعرفنا في هذا المقال على العديد من الطرق للتعامل مع المصفوفات، إذ تعلمنا كيفية الوصول إلى عناصرها والبحث واستخراج بعض القيم منها وترتيب العناصر وتحويل البيانات ضمنها وإنشاء مصفوفات وسلاسل نصية وقيمة مجموع كلي جديدة. تفيد كل تلك المفاهيم في حل العديد من المشاكل البرمجية باستخدام لغة روبي وهي من أهم المهارات التي يجب على المبرمج اكتسابها.
لمزيد من التفصيل، ارجع إلى صفحة النوع Array في موسوعة حسوب.
ترجمة -وبتصرف- للمقال How To Use Array Methods in Ruby لصاحبه Brian Hogan.
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.