Книга: Программирование на языке Ruby
8.3.6. Энумераторы
8.3.6. Энумераторы
Объект класса Enumerator
— по существу, обертка, превращающая итераторный метод в полноценный объект Enumerable
. Обернутый таким способом итератор приобретает все методы и свойства, присущие перечисляемым структурам.
В следующем искусственном примере в классе Foo
есть итератор и больше ничего. Да и сам-то итератор не делает ничего полезного, только четыре раза вызывает yield
. Чтобы подчеркнуть особенность его работы, итератор назван every
, а не each
.
require 'enumerator'
class Foo
def every
yield 3
yield 2
yield 1
yield 4
end
end
foo = Foo.new
# Передается объект и имя итератора...
enum = Enumerable::Enumerator, new(foo, :every)
enum.each {|x| p x } # Печатаются элементы
array = enum.to_a # [3,2,1,4]
sorted = enum.sort # [1,2,3,4]
Преобразование выглядит загадочно, но, по сути, это не что иное как:
enum = []
foo.every {|x| enum << x }
В примере выше enum
— настоящий массив, а не просто объект Enumerator
. Как следствие, несмотря на некоторые тонкие различия, это еще один способ преобразовать объект в перечисляемую структуру Enumerable
.
Если затребована библиотека enumerator
, то в классе object
появляется метод enum_for
. Поэтому создание объекта в первом примере можно записать компактнее:
enum = fоо.enum_for(:every)
Мы уже видели, как итераторы each_slice
и each_cons
позволяют осуществлять обход с группировкой. Оказывается, что есть специальные методы enum_slice
и enum_cons
, которые создают из таких итераторов объекты-энумераторы (по существу, трансформируя имя итератора в each
). Имейте в виду, что методы Enumerable::Enumerator.new
и enum_for
могут принимать необязательный список аргументов в качестве последнего параметра. Ниже мы воспользовались этим для передачи итератору «размера окна»:
array = [5,3,1,2]
discrete = array.enum_slice(2)
# To же, что Enumerable::Enumerator.new(array,:each_slice,2)
overlap = array.enum_cons(2)
# To же, что Enumerable::Enumerator.new(array,:each_cons,2)
discrete.each {|x| puts x.join(",") }
# Выводится:
# 5,3
# 1,2
overlap.each {|x| puts x.join(",") )
# Выводится:
# 5,3
# 3,1
# 1,2
- 8.3.4. Обход с группировкой
- Chapter 5. Kernel Initialization
- Кто такая Елена Ивашенцева?
- 11.2. Цели процесса
- Рис. 214. Имена почтовых серверов.
- Document
- ГЛАВА 3 Внутренняя структура .NET Compact Framework
- Джордж Буль Отец булевой алгебры
- Removable Storage Media
- Работа пользователей с виртуальной машиной