Enumerable 모듈
Coddy Ruby 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 57개 중 30번째.
Enumerable은 배열과 해시의 컬렉션 메서드가 구현된 모듈입니다. each를 정의해 요소를 하나씩 yield하고 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요소가 <=>를 정의하면 sort, min, max와 같은 Enumerable의 정렬 메서드는 블록 없이 작동합니다. 그렇지 않으면 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 클래스를 완성하세요. 이 클래스는 add를 사용해 추가된 Song 객체(title과 seconds 포함)를 보관하고, Enumerable을 포함하며, 추가된 순서대로 모든 노래를 yield하는 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(", ")}"
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
직접 연습해 보세요: 온라인 Ruby 컴파일러