رمز قابل للطي على التوالي جمع/تحديد/رفض/كل
سؤال
أتلاعب بالمصفوفات والتجزئة كثيرًا في روبي وينتهي بي الأمر ببعض التعليمات البرمجية التي تبدو كما يلي:
sum = two_dimensional_array.select{|i|
i.collect{|j|
j.to_i
}.sum > 5
}.collect{|i|
i.collect{|j|
j ** 2
}.average
}.sum
(دعونا نتظاهر جميعًا بأن نموذج التعليمات البرمجية أعلاه أصبح منطقيًا الآن...)
المشكلة هي أنه على الرغم من أن TextMate (المحرر المفضل لدي) يلتقط بشكل بسيط {...}
أو do...end
الكتل بسهولة تامة، لا يمكن معرفة (وهو أمر مفهوم لأنني حتى لا أستطيع العثور على طريقة "صحيحة" لطي ما ورد أعلاه) حيث تبدأ الكتل المذكورة أعلاه وتنتهي في طيها.
كيف يمكنك طي نموذج التعليمات البرمجية أعلاه؟
ملاحظة:مع الأخذ في الاعتبار أنه يمكن أن يحتوي على مستويين من الطي، فأنا أهتم فقط بالمستويين المتتاليين الخارجيين (الكتل التي تحتوي على i)
المحلول
لكي نكون صادقين، فإن الشيء الملتوي ربما يكون مربكًا لـ TextMate بقدر ما يربك أي شخص آخر يتعين عليه الحفاظ عليه، وهذا يشملك في المستقبل.
عندما ترى شيئًا ما يتحول إلى قيمة واحدة، فهذه حالة جيدة لاستخدام Enumerable#inject.
sum = two_dimensional_array.inject(0) do |sum, row|
# Convert row to Fixnum equivalent
row_i = row.collect { |i| i.to_i }
if (row_i.sum > 5)
sum += row_i.collect { |i| i ** 2 }.average
end
sum # Carry through to next inject call
end
الأمر الغريب في مثالك هو أنك تستخدم التحديد لإرجاع المصفوفة الكاملة، والتي يُزعم أنها تم تحويلها باستخدام to_i، لكن في الواقع Enumerable#select لا يفعل شيئًا من هذا القبيل، وبدلاً من ذلك يرفض أي شيء ترجع فيه الدالة صفرًا.أفترض أن هذا ليس من قيمك.
اعتمادًا أيضًا على كيفية تنفيذ أسلوب .average الخاص بك، قد ترغب في زرع استدعاء الحقن بـ 0.0 بدلاً من 0 لاستخدام قيمة الفاصلة العائمة.