ruby get next value on each loop

12,615

Solution 1

Like this:

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

There may be better ways, but this works.

You can get the next of the next value like this:

range.to_a[i+2]

Solution 2

From as early as Ruby 1.8.7, the Enumerable module has had a method each_cons that does almost exactly what you want:

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

Iterates the given block for each array of consecutive <n> elements. If no block is given, returns an enumerator.

e.g.:

(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]

The only problem is that it doesn't repeat the last element. But that's trivial to fix. Specifically, you want

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

But you could also do this:

range = 1..5

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

p result # => 29

Alternatively, you may find the following to be more readable:

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

Solution 3

One approach that wouldn't use indexes is 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
Share:
12,615
jovhenni19
Author by

jovhenni19

Updated on June 17, 2022

Comments

  • jovhenni19
    jovhenni19 about 2 years

    Can I get the next value in an each loop?

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

    where the answer would be..

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

    And also can I get the next of the next value?

  • oligan
    oligan over 12 years
    This code would break if range were changed, such as to 11..15: it'd give 65 when it should give 119.
  • jovhenni19
    jovhenni19 over 12 years
    nice! thanks for your quick reply! On second thought, @AndrewGrimm was right.
  • Mischa
    Mischa over 12 years
    @jovhenni19, I updated my answer so it works with AndrewGrimm's example too.
  • Mischa
    Mischa over 12 years
    Thanks for spotting my mistakes :-)