Menu
Coddy logo textTech

Enumerable 모듈

Coddy Ruby 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 57개 중 30번째.

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

요소가 <=>를 정의하면 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)
challenge icon

챌린지

쉬움

Playlist 클래스를 완성하세요. 이 클래스는 add를 사용해 추가된 Song 객체(title과 seconds 포함)를 보관하고, 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 컴파일러