назвал его classify по аналогии с методом из класса Set.

module Enumerable

 def classify(&block)

  hash = {}

  self.each do |x|

   result = block.call(x)

   (hashfresult] ||= []) << x

  end

  hash

 end

end

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

mod3 = nums.classify {|x| x % 3 }

# { 0=>[3,6,9], 1=>[1,4,7], 2=>[2,5,8] }

words = %w( area arboreal brick estrous clear donor ether filial

patina ]

vowels = words.classify {|x| x.count('aeiou') }

# {1=>['brick'], 2=>['clear', 'donor', 'ether'],

#  3=>['area', 'estrous', 'filial', 'patina'], 4=>['arboreal']}

initials = words.classify {|x| x[0..0] }

# {'a'=>['area', 'arboreal'], 'b'=>['brick'], 'c'=>['clear'],

#  'd'=>['donor'], 'p'=>['patina'], 'e'=>['estrous', 'ether'],

#  'f'=>['filial']}

8.3.4. Обход с группировкой

До сих пор мы обходили список по одному элементу за раз. Но иногда желательно на каждой итерации анализировать по два, три или более элементов.

Итератор each_slice принимает в качестве параметра число n, равное числу просматриваемых на каждой итерации элементов. (Для работы с ним нужна библиотека enumerator.) Если не осталось достаточного количества элементов, размер последнего фрагмента будет меньше.

require 'enumerator'

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

arr.each_slice(3) do |triple|

 puts triple.join(',')

end

# Выводится:

# 1,2,3

# 4,5,6

# 7,8,9

# 10

Имеется также итератор each_cons, который позволяет обходить набор методом «скользящего окна» заданного размера. (Если название кажется вам странным, знайте, что это наследие языка Lisp.) В таком случае фрагменты всегда будут иметь одинаковый размер.

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

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату