Michael Hebblethwaite

Things I would forget otherwise

TIL - with_index

I was doing a coding challenge where I wanted to map through an array transforming the current element based on the previous element. Sounds convoluted, but then I again feel most coding challenges are. Maybe that’s part of the fun though.

Anyway Ruby has a nice method, .each_with_index, that exposes the element along with its index.

favourite_fruits = %w[raspberries strawberries blueberries]
favourite_fruits.each_with_index do |fruit, index|
  p "#{index}. #{fruit}"
end

With the expected out put below.

0. raspberries
1. strawberries
2. blueberries

This is great for most programmers, but many people in the world start counting from 1, not 0. So instead we could offset the index inside the block.

favourite_fruits.each_with_index do |fruit, index|
  offset_index = index + 1
  p "#{offset_index}. #{fruit}"
end

Which gives us the following.

1. raspberries
2. strawberries
3. blueberries

But today I learned that .with_index takes an integer offset argument that sets the starting index to use, removing the need to have an operation to generate the offset in the block.

favourite_fruits.each.with_index(1) do |fruit, offset_index|
  p "#{offset_index}. #{fruit}"
end

Of course the output is the same as before, but maybe the code is a little cleaner?

It’s important to note that .each_with_index does not accept the offset argument.

.with_index can be used on any Enumerable, so I was able to complete the challenge by providing an offset of -1 to fetch the value of the previous element in array during each step of the map.