Menu
Coddy logo textTech

Collezioni personalizzate

Fa parte della sezione Programmazione orientata agli oggetti del percorso Ruby di Coddy. Lezione 40 di 57.

Una classe collezione combina diversi metodi speciali: each con Enumerable, << per aggiungere, size e to_s e inspect per stampare. each dovrebbe funzionare anche senza un blocco, restituendo un enumeratore con to_enum, come fanno gli array:

class TodoList
  include Enumerable

  def initialize
    @items = []
  end

  def <<(item)
    @items << item
    self
  end

  def each
    return to_enum(:each) unless block_given?

    @items.each { |item| yield item }
    self
  end
end

list = TodoList.new << "wash" << "shop" << "cook"
list.each.with_index(1) { |item, n| puts "#{n}. #{item}" }
p list.select { |i| i.include?("o") }

Output:

1. wash
2. shop
3. cook
["shop", "cook"]

block_given? indica se il chiamante ha passato un blocco. L’enumeratore restituito quando non ne viene passato uno supporta concatenamenti come each.with_index, each_slice o next:

class Countdown
  include Enumerable

  def initialize(from)
    @from = from
  end

  def each
    return to_enum(:each) unless block_given?

    @from.downto(1) { |n| yield n }
  end
end

e = Countdown.new(3).each
puts e.next
puts e.next
p Countdown.new(5).each_slice(2).to_a

Output:

3
2
[[5, 4], [3, 2], [1]]

to_s è il testo intuitivo per gli utenti, mentre inspect è un breve riepilogo per i programmatori. Per una raccolta, inspect mostra di solito la classe e le dimensioni invece di ogni elemento:

class TodoList
  include Enumerable

  def initialize(*items)
    @items = items
  end

  def each(&block)
    @items.each(&block)
  end

  def size
    @items.size
  end

  def to_s
    map.with_index(1) { |item, n| "#{n}. #{item}" }.join("\n")
  end

  def inspect
    "#<TodoList #{size} items>"
  end
end

list = TodoList.new("wash", "shop")
puts list
p list

Output:

1. wash
2. shop
#<TodoList 2 items>

Enumerable fornisce count, ma non size, empty?, << o []: questi appartengono alla classe, perché solo essa sa come vengono memorizzati gli elementi. Definirli fa sì che la raccolta sembri un array a chi la usa:

def size
  @items.size
end

def empty?
  @items.empty?
end

def [](index)
  @items[index]
end
challenge icon

Sfida

Facile

Completa la classe TodoList. << aggiunge il testo di un'attività e restituisce la lista. each restituisce le attività tramite yield e restituisce to_enum(:each) se non viene fornito un blocco. Includi Enumerable. size restituisce il numero di attività. to_s restituisce le attività come righe numerate, 1. wash, oppure nothing to do, e inspect restituisce #<TodoList 3 items>.

Il codice fornito aggiunge ogni riga di input concatenando <<, poi stampa la lista, p della lista, le attività numerate con ! tramite each.with_index(1) come 1! wash, il numero di attività che contengono o e la prima attività in ordine alfabetico.

Il tuo codice va in todo_list.rb. main.rb contiene il codice di input/output fornito e non può essere modificato.

Provalo tu

require_relative 'todo_list'

# Supplied input/output code: keep it as it is
input = []
while (line = gets)
  input << line.chomp
end
list = input.reduce(TodoList.new) { |l, task| l << task }
puts list
p list
list.each.with_index(1) { |task, n| puts "#{n}! #{task}" }
puts "with o: #{list.count { |t| t.include?("o") }}"
puts "first: #{list.min}"
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Ruby online