Подтвердить что ты не робот

Ruby получить следующее значение для каждого цикла

Можно ли получить следующее значение в каждом цикле?

(1..5).each do |i|
    @store = i + (next value of i)
end

где ответ будет...

1 + 2 + 2 + 3 + 3 + 4 + 4 + 5 + 5 = 29

А также я могу получить следующее из следующего значения?

4b9b3361

Ответ 1

Вот так:

range = 1..5
store = 0

range.each_with_index do |value, i|
  next_value = range.to_a[i+1].nil? ? 0 : range.to_a[i+1]
  store += value + next_value
end    

p store # => 29

Там могут быть лучшие способы, но это работает.

Вы можете получить следующее следующее значение, подобное этому:

range.to_a[i+2]

Ответ 2

Начиная с Ruby 1.8.7, модуль Enumerable имел метод each_cons, которая делает практически то, что вы хотите:

each_cons (n) {...} → nil
each_cons (n) → an_enumerator

Итерирует заданный блок для каждого массива последовательных <n> элементы. Если ни один блок не указан, возвращает перечислитель.

например.:

(1..10).each_cons(3) { |a| p a }
# outputs below
[1, 2, 3]
[2, 3, 4]
[3, 4, 5]
[4, 5, 6]
[5, 6, 7]
[6, 7, 8]
[7, 8, 9]
[8, 9, 10]

Единственная проблема заключается в том, что он не повторяет последний элемент. Но это тривиально исправить. В частности, вы хотите

store = 0
range = 1..5

range.each_cons(2) do |i, next_value_of_i|
    store += i + next_value_of_i
end
store += range.end

p store # => 29

Но вы также можете это сделать:

range = 1..5

result = range.each_cons(2).reduce(:+).reduce(:+) + range.end

p result # => 29

В качестве альтернативы вы можете найти следующее:

result = range.end + range.each_cons(2)
                          .reduce(:+)
                          .reduce(:+)

Ответ 3

Один подход, который не использовал бы индексы, - Enumerable # zip:

range = 11..15
store = 0 # This is horrible imperative programming
range.zip(range.to_a[1..-1], range.to_a[2..-1]) do |x, y, z|
  # nil.to_i equals 0
  store += [x, y, z].map(&:to_i).inject(:+)
end
store