Вход/Регистрация
Программирование на языке Ruby
вернуться

Фултон Хэл

Шрифт:

require 'enumerator'

arr = [1,2,3,4,5,6,7,8,9,10]

arr.each_cons(3) do |triple|

 puts triple.join(",")

end

# Выводится:

# 1,2,3

# 2,3,4

# 3,4,5

# 4,5,6

# 5,6,7

# 6,7,8

# 7,8,9

# 8,9,10

8.3.5. Преобразование в массив или множество

Каждая перечисляемая структура теоретически может быть тривиально преобразована в массив (методом

to_a
). Например, такое преобразование для хэша дает вложенный массив пар:

hash = {1=>2, 3=>4, 5=>6}

arr = hash.to_a # [[5, 6], [1, 2], [3, 4]]

Синонимом

to_a
является метод
entries
.

Если была затребована библиотека

set
, становится доступен также метод
to_set
. Дополнительная информация о множествах приведена в разделе 9.1.

require 'set'

hash = {1=>2, 3=>4, 5=>6}

set = hash.to_set # #<Set: {[1, 2], [3, 4], [5, 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.7. Объекты-генераторы

Идея генератора довольно интересна. Обычный итератор в Ruby является внутренним, он запускает некоторый алгоритм, повторно вызывая блок кода.

Но бывают также и внешние итераторы. В этом случае алгоритм запускается самой программой, а итератор поставляет данные «по запросу», а не в соответствии с собственным «графиком».

  • Читать дальше
  • 1
  • ...
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: