Про модуль Enumerable в Ruby

Модуль Enumerable – це вбудований модуль в мові програмування Ruby, який надає набір методів для ітерації, сортування, пошуку та трансформації колекцій. Він широко використовується в класах, які підтримують ітерацію, таких як Array, Hash, Range та інші.

Основні особливості

  1. Модуль включає методи для обробки колекцій, такі як map, select, reject, reduce, each_with_index, include?, count та багато інших.

  2. Для того, щоб клас міг використовувати функціонал Enumerable, він повинен реалізовувати метод each, який проходить по елементах колекції.

  3. Завдяки використанню Enumerable, розробники можуть працювати з колекціями на більш високому рівні абстракції, замість написання ручних циклів. Це робить код більш декларативним

Приклади використання

1. Використання select та reject

numbers = [1, 2, 3, 4, 5, 6]
even_numbers = numbers.select { |n| n.even? }  # => [2, 4, 6]
odd_numbers = numbers.reject { |n| n.even? }   # => [1, 3, 5]

2. Підрахунок елементів за умовою (count)

words = ["apple", "banana", "avocado", "grape"]
count_a = words.count { |word| word.start_with?("a") }  # => 2

3. Використання map для трансформації

numbers = [1, 2, 3, 4, 5]
squared_numbers = numbers.map { |n| n**2 }  # => [1, 4, 9, 16, 25]

4. Агрегація значень (reduce / inject)

sum = numbers.reduce(0) { |acc, n| acc + n }  # => 15

5. Пошук значень (find, any?, all?, none?)

words = ["cat", "dog", "elephant"]
long_word = words.find { |word| word.length > 3 }  # => "elephant"
all_short = words.all? { |word| word.length < 10 } # => true
any_long = words.any? { |word| word.length > 10 }  # => false

Власний клас з підтримкою Enumerable

Якщо ми створюємо свій клас і хочемо, щоб він підтримував методи Enumerable, достатньо реалізувати each і підключити модуль:

class Playlist
  include Enumerable

  def initialize(songs)
    @songs = songs
  end

  def each
    @songs.each { |song| yield song }
  end
end

playlist = Playlist.new(["Song 1", "Song 2", "Song 3"])
playlist.each { |song| puts song } # Виведе кожну пісню
puts playlist.map(&:upcase)        # => ["SONG 1", "SONG 2", "SONG 3"]

Модуль Enumerable значно спрощує роботу з колекціями, надаючи широкий набір функцій для обробки даних. Його основна перевага – це декларативний підхід до роботи з ітераціями, що робить код більш чистим, читабельним і ефективним.