Menu
CoddyTech

המודול 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)
challenge icon

אתגר

קל

השלימו את המחלקה 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(", ")}"
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר Ruby אונליין