group_by و partition
جزء من قسم المنطق وتدفق العمليات في رحلة Ruby على Coddy — الدرس 25 من 56.
في بعض الأحيان قد ترغب في تقسيم مجموعة بدلاً من تصفيتها. هناك طريقتان تغطيان معظم الحالات.
تأخذ group_by كتلة (block) وتعيد hash. تصبح كل نتيجة فريدة للكتلة مفتاحاً (key)، يشير إلى مصفوفة من العناصر التي أنتجتها:
words = ["hi", "hello", "yo", "hey", "bonjour"]
by_length = words.group_by { |w| w.length }
puts by_length.inspect
# {2=>["hi", "yo"], 5=>["hello"], 3=>["hey"], 7=>["bonjour"]}إنها أنظف طريقة لتصنيف العناصر في تمريرة واحدة.
partition هي النسخة الثنائية: فهي تُعيد زوجاً من المصفوفات، العناصر التي كانت فيها الكتلة (block) صحيحة (true)، والباقي:
evens, odds = [1, 2, 3, 4, 5].partition { |n| n.even? }
puts evens.inspect # [2, 4]
puts odds.inspect # [1, 3, 5]استخدم partition عندما يكون هناك مجموعتان بالضبط، و group_by عندما يمكن أن يكون هناك الكثير.
التحدي
متوسطاقرأ قائمة مفصولة بفاصلة من مدخلات name:score (على سبيل المثال Alice:88,Bob:42,Charlie:75). استخدم group_by متبوعة بـ partition لإنشاء تقرير صغير.
الخطوات:
- قم بتحليل كل مدخل إلى زوج
[name, score](الدرجة score هي عدد صحيح) - استخدم
group_byلتجميع الأزواج بناءً على الحرف الأول منname(بصيغة uppercase) - لكل مجموعة أحرف، وبالترتيب الأبجدي، استخدم
partitionلتقسيم المدخلات إلى ناجح (score >= 60) و راسب، ثم اطبع سطراً واحداً لكل مجموعة:
<LETTER>: pass=<names_passing_joined_by_comma> fail=<names_failing_joined_by_comma>داخل كل مجموعة، تظهر الأسماء بترتيبها الأصلي. إذا كان أحد الجانبين لا يحتوي على أسماء، فاتركه فارغاً (على سبيل المثال fail=).
للمدخل Alice:88,Adam:42,Bob:75,Beth:55,Cara:90، يكون المخرج:
A: pass=Alice fail=Adam
B: pass=Bob fail=Beth
C: pass=Cara fail=ورقة مرجعية
يقوم group_by بتقسيم مجموعة إلى hash مفتاحه هو نتيجة الـ block:
words = ["hi", "hello", "yo"]
by_length = words.group_by { |w| w.length }
# {2=>["hi", "yo"], 5=>["hello"]}يقوم partition بالتقسيم إلى مصفوفتين بالضبط (المطابقة وغير المطابقة):
evens, odds = [1, 2, 3, 4, 5].partition { |n| n.even? }
# evens => [2, 4], odds => [1, 3, 5]استخدم partition لتقسيمين، و group_by للمجموعات المتعددة.
جرّب بنفسك
entries = gets.chomp.split(",").map do |s|
name, score = s.split(":")
[name, score.to_i]
end
# مهمة: التجميع حسب الحرف الأول (كبير)، تقسيم كل مجموعة حسب الدرجة >= 60،
# طباعة 'X: pass=... fail=...' بترتيب الحروف الأبجدي
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس المنطق وتدفق العمليات
1السلاسل النصية بعمق
نظرة عامة على دوال السلاسل النصيةتضمين النصوص (String Interpolation)التكرار عبر السلاسل النصيةالتقسيم والربط (Split و Join)مراجعة - نساج النصوص4Blocks و Procs و Lambdas
ما هو الـ Block؟do..end مقابل الأقواس { }الكلمة المفتاحية yieldمعاملات الـ BlockProcs و Lambdasمراجعة - Custom Iterator مخصص7Hashes - الجزء الثاني
Hash.new مع القيم الافتراضيةالتكرار عبر الـ Hashesالـ Hashes المتداخلةالدمج والتحويلمراجعة - عداد التكرار10مشروع - سجلات الطلاب
نظرة عامة على المشروعإضافة طالب5قوة الـ Enumerable
Select و Rejectتسلسل MapReduce / Injectcount، all?، any?، none?group_by و partitionsort_by، min_by، max_byمراجعة - Data Pipeline