وحدة Enumerable
جزء من قسم البرمجة كائنية التوجه في رحلة Ruby على Coddy. الدرس 30 من 57.
الوحدة Enumerable هي الأساس وراء أساليب المجموعات الخاصة بالمصفوفات والتجزئات. ويحصل أي صنف يعرّف each، ويُمرّر عناصره واحدًا تلو الآخر، ويضمّن Enumerable، على map وselect وcount وsort_by وmin_by وsum وinclude? وعشرات غيرها:
class Playlist
include Enumerable
def initialize(*songs)
@songs = songs
end
def each
@songs.each { |song| yield song }
end
end
list = Playlist.new("Intro", "Dune", "Outro")
puts list.map(&:upcase).join(", ")
puts list.select { |s| s.size > 4 }.inspect
puts list.count
puts list.include?("Dune")الناتج:
INTRO, DUNE, OUTRO
["Intro", "Outro"]
3
trueيمرّر yield قيمةً إلى الكتلة التي يمرّرها المستدعي إلى each. تحدد الفئة ماهية العنصر الواحد، مثل سطر نصي، أو زوج من القيم، أو أحد كائناتها:
class Inventory
include Enumerable
def initialize
@stock = { "apple" => 3, "pear" => 0, "plum" => 7 }
end
def each
@stock.each { |name, qty| yield name, qty }
end
end
inv = Inventory.new
p inv.select { |_, qty| qty.positive? }.map(&:first)
p inv.max_by { |_, qty| qty }الناتج:
["apple", "plum"]
["plum", 7]لا يلزم تخزين العناصر. يمكن لـ each حسابها أثناء التقدّم، وتُوقِف طرق مثل first الحلقة مبكرًا:
class Squares
include Enumerable
def initialize(limit)
@limit = limit
end
def each
n = 1
while n * n <= @limit
yield n * n
n += 1
end
end
end
p Squares.new(50).to_a
p Squares.new(1000).first(3)
puts Squares.new(100).sumالناتج:
[1, 4, 9, 16, 25, 36, 49]
[1, 4, 9]
385عندما تُعرّف العناصر <=>، تعمل طرائق الفرز في Enumerable، مثل sort وmin وmax، دون كتلة. وإلا فإنها تتطلب كتلة، كما في sort_by وmin_by:
class Team
include Enumerable
def each(&block)
@players.each(&block) # مرّر الكتلة مباشرةً
end
end
team.sort_by(&:age)
team.min_by(&:score)التحدي
سهلأكمل الصنف Playlist. يحتفظ بكائنات Song (التي تحتوي على title وseconds) تُضاف باستخدام add، ويضمّن Enumerable ويعرّف each، الذي يمرّر كل أغنية بالترتيب الذي أُضيفت به.
يضيف الكود المزوّد أغنية واحدة لكل سطر إدخال (title,seconds)، ثم يستخدم أساليب Enumerable فقط على قائمة التشغيل: يطبع عدد الأغاني، والعناوين مفصولة بفواصل، والمدة الإجمالية بتنسيق m:ss، وعنوان أطول أغنية، وعناوين الأغاني التي تتجاوز مدتها 3 دقائق، مرتبة أبجديًا (أو none).
ضع الكود في song.rb وplaylist.rb. يحتوي main.rb على كود الإدخال/الإخراج المزوّد ولا يمكن تعديله.
جرّب بنفسك
require_relative 'song'
require_relative 'playlist'
# كود الإدخال/الإخراج المقدَّم: أبقه كما هو
input = []
while (line = gets)
input << line.chomp
end
list = Playlist.new
input.each do |line|
title, seconds = line.split(",")
list.add(Song.new(title, seconds.to_i))
end
total = list.sum(&:seconds)
long = list.select { |s| s.seconds > 180 }.map(&:title).sort
puts "songs: #{list.count}"
puts "titles: #{list.map(&:title).join(", ")}"
puts format("total: %d:%02d", total / 60, total % 60)
puts "longest: #{list.max_by(&:seconds).title}"
puts "over 3 min: #{long.empty? ? "none" : long.join(", ")}"
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1الفئات والكائنات
العمل مع الملفاتتعريف الفئاتمتغيرات النسخةالأساليب و selfto_s و inspectمراجعة - بطاقة المكتبة7تعدد الأشكال والكتابة بأسلوب البطة
تعدد الأشكالالكتابة بأسلوب البطةالأساليب المجردةالحالات والفئاتمراجعة - طرق الدفع3أساليب ومتغيرات الأصناف
أساليب الأصنافمتغيرات كائنات الأصنافالثوابتأساليب الإنشاءمراجعة - رموز القسائمتدرّب بنفسك: مترجم Ruby عبر الإنترنت