Разделите массив на диапазоны, где элементы в каждом диапазоне должны вести себя по-разному. Сопоставьте каждый диапазон, созданный таким образом, с блоком.
class PartitionEnumerator
include RangeMaker
def initialize(array)
@array = array
@handlers = {}
end
def add(range, handler)
@handlers[range] = handler
end
def iterate
@handlers.each_pair do |range, handler|
@array[range].each { |value| puts handler.call(value) }
end
end
end
Может создавать диапазоны вручную, но эти помощники ниже облегчают:
module RangeMaker
def create_range(s)
last_index = @array.size - 1
indexes = (0..last_index)
return (indexes.first..indexes.first) if s == :first
return (indexes.second..indexes.second_last) if s == :middle
return (indexes.last..indexes.last) if s == :last
end
end
class Range
def second
self.first + 1
end
def second_last
self.last - 1
end
end
Использование:
a = [1, 2, 3, 4, 5, 6]
e = PartitionEnumerator.new(a)
e.add(e.create_range(:first), Proc.new { |x| x + 1 } )
e.add(e.create_range(:middle), Proc.new { |x| x * 10 } )
e.add(e.create_range(:last), Proc.new { |x| x } )
e.iterate