اذهب إلى المحتوى

توابع المصفوفات في لغة روبي


Hassan Hedr

تسمح المصفوفات 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.

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...