Working with Ruby Arrays: Map with Index

April 01, 2011 · 1 min read

Here's a handy little method I keep reaching for: map_with_index. It does exactly what you'd expect — it works like each_with_index but with the return-value behaviour of map. Every element in the resulting array is whatever the block returns when that element and its index are yielded to it.

module BarkingIguana
  module ArrayExt
    def map_with_index &block
      index = 0
      map do |element|
        result = yield element, index
        index += 1
        result
      end
    end
  end
end

Array.class_eval do
  include BarkingIguana::ArrayExt
end

This is particularly useful when the first N elements of an array need to be treated differently from the rest:

[1, 2, 3, 4, 5].map_with_index do |element, index|
  model = Model.new element
  model.unlock if index < 3
  model
end

Note that Ruby 1.9.3+ gives you each_with_index.map and later versions provide each_with_object and other enumerator-chaining tricks that can achieve similar results — but sometimes a purpose-built method just reads better.