Модуль 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
trueyield передаёт значение блоку, который вызывающий код передал в 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Повторение — читательский билет4Инкапсуляция
Приватные методыЗащищённые методыПриватные сеттерыЗащита состоянияПовторение — торговый автомат7Полиморфизм и утиная типизация
ПолиморфизмУтиная типизацияАбстрактные методыcase и классыПовторение — способы оплаты10Шаблоны проектирования, часть 2
Делегирование с помощью ForwardableШаблон декоратораШаблон строителяШаблон состояния2Аксессоры и self
Чтение и записьПользовательские сеттерыself в методахИдентичность и равенствоПовторение — список контактов5Наследование
ПодклассыПереопределение методовВызов superis_a? и предкиПовторение — расчёт зарплаты сотрудников8Специальные методы
Равенство и хешированиеМетоды операторовИндексация и добавлениеПользовательские коллекцииПовторение — дроби11Проект: Управление библиотекой
Книги и читателиВыдача книг3Методы и переменные классов
Методы классовПеременные экземпляра классаКонстантыФабричные методыПовторение — коды купонов6Модули и примеси
Модули и includeРасширение объектовМодуль ComparableМодуль EnumerableПовторение — спортивная лига9Паттерны проектирования. Часть 1
Паттерн «Одиночка»Фабричный паттернПаттерн «Наблюдатель»Паттерн «Стратегия»Потренируйтесь самостоятельно: Онлайн-компилятор Ruby