How to map with index in Ruby?



What is the easiest way to convert

[x1, x2, x3, ... , xN]


[[x1, 2], [x2, 3], [x3, 4], ... , [xN, N+1]]

Misha Moroshko

Posted 2011-01-15T01:34:34.580

Reputation: 60 422



If you're using ruby 1.8.7 or 1.9, you can use the fact that iterator methods like each_with_index, when called without a block, return an Enumerator object, which you can call Enumerable methods like map on. So you can do: { |x,i| [x, i+2] }

In 1.8.6 you can do:

require 'enumerator'
arr.enum_for(:each_with_index).map { |x,i| [x, i+2] }


Posted 2011-01-15T01:34:34.580

Reputation: 290 410

only semi related, this also has some good info on enumerator:

– jtzero – 2012-11-15T17:20:31.927

2Important to note this doesn't work with .map! if you want to directly affect the array you're looping on. – Ash Blue – 2013-07-25T17:38:56.563

Thanks! Could you give me a pointer to documentation for ? – Misha Moroshko – 2011-01-15T01:41:05.960

In this case map is a function of what ? – Misha Moroshko – 2011-01-15T01:41:44.490

1@Misha: map is a method of Enumerable as always. each_with_index, when called without a block, returns an Enumerator object (in 1.8.7+), which mixes in Enumerable, so you can call map, select, reject etc. on it just like on an array, hash, range etc. – sepp2k – 2011-01-15T01:45:41.530

7IMO this is simpler and better-reading in 1.8.7+:{ |o,i| [o,i+2] } – Phrogz – 2011-01-15T02:43:29.870

4@Phrogz: map.with_index doesn't work in 1.8.7 (map returns an array when called without a block in 1.8). – sepp2k – 2011-01-15T02:50:24.633

Oops; good to know. I moved from 1.8.6 to 1.9 and have never seen the use of 1.8.7 since. My apologies to those who use 1.8.7. – Phrogz – 2011-01-15T02:58:15.290

x and i is not descriptive enough for the purpose of answering general questions. It might serve you as your personal convention, but I am not certain i refers to index. – Ekkstein – 2016-10-18T11:41:32.020


Ruby has Enumerator#with_index(offset = 0), so first convert the array to an enumerator using Object#to_enum or Array#map:

[:a, :b, :c].map.with_index(2).to_a
#=> [[:a, 2], [:b, 3], [:c, 4]]


Posted 2011-01-15T01:34:34.580

Reputation: 51 280

9This is the best answer so far! – David J. – 2012-08-22T21:27:13.783

3Very elegant solution, thanks! – dolzenko – 2013-10-23T10:59:32.280

10I believe this is the better answer, because it will work with map! foo = ['d'] * 5;!.with_index { |x,i| x * i }; foo #=> ["", "d", "dd", "ddd", "dddd"] – Connor McKay – 2014-02-27T21:47:52.470

Money in the bank. Praise be to Matz et al. – Joshua Pinter – 2015-05-28T00:09:08.473


In ruby 1.9.3 there is a chainable method called with_index which can be chained to map.

For example: { |item, index| ... }


Posted 2011-01-15T01:34:34.580

Reputation: 2 120


Over the top obfuscation:

arr = ('a'..'g').to_a
indexes =

Andrew Grimm

Posted 2011-01-15T01:34:34.580

Reputation: 43 291

11Andrew must have great job security! :) – David J. – 2012-07-19T06:36:27.217

9i like that one, obscure code is always fun to maintain. – Jeff Ancel – 2011-11-10T03:43:24.730


Here are two more options for 1.8.6 (or 1.9) without using enumerator:

# Fun with functional
arr = ('a'..'g').to_a (2..(arr.length+2)).to_a )
#=> [["a", 2], ["b", 3], ["c", 4], ["d", 5], ["e", 6], ["f", 7], ["g", 8]]

# The simplest
n = 1{ |c| [c, n+=1 ] }
#=> [["a", 2], ["b", 3], ["c", 4], ["d", 5], ["e", 6], ["f", 7], ["g", 8]]


Posted 2011-01-15T01:34:34.580

Reputation: 218 646


I have always enjoyed the syntax of this style:

a = [1, 2, 3, 4] { |el, index| el + index }
# => [1, 3, 5, 7]

Invoking each_with_index gets you an enumerator you can easily map over with your index available.


Posted 2011-01-15T01:34:34.580

Reputation: 542


how is this different form the answer, given almost 5 years before yours?

– Andrey Deineko – 2016-06-01T09:53:03.400


a = [1, 2, 3]
p [a, (2...a.size+2).to_a].transpose

Nikolay Bobrovskiy

Posted 2011-01-15T01:34:34.580

Reputation: 72


module Enumerable
  def map_with_index(&block)
    i = 0 { |val|
      val =, i)
      i += 1

["foo", "bar"].map_with_index {|item, index| [item, index] } => [["foo", 0], ["bar", 1]]

Mo Wad

Posted 2011-01-15T01:34:34.580

Reputation: 37

3OMG! Did you even read the other answers? map.with_index already exists in ruby. Why suggest to reopen the enumerable class and add something that already exists? – nathanvda – 2014-11-28T12:10:02.040

This might be an easier way to go for 1.8.6 and 1.8.7 (yes some of us still use it) instead of having to use weirder stuff like etc. and even those of us on newer versions might prefer it to having to use map.with_index FWIW :) – rogerdpack – 2017-03-13T16:42:06.170


I often do this:

arr = ["a", "b", "c"]

(0...arr.length).map do |int|
  [arr[int], int + 2]

#=> [["a", 2], ["b", 3], ["c", 4]]

Instead of directly iterating over the elements of the array, you're iterating over a range of integers and using them as the indices to retrieve the elements of the array.


Posted 2011-01-15T01:34:34.580

Reputation: 679

1If you read the other answers, I hope you now realise there are better approaches. So not sure why you needed to add this. – nathanvda – 2014-11-28T12:05:36.313

If Andrew Grimm's answer deserves ten votes, then this one deserves at least one! – Camille Goudeseune – 2017-05-18T20:20:09.333

I think you ought to throw in a for loop for good measure ;) – M.G.Palmer – 2017-12-19T16:49:54.387


A fun, but useless way to do this:

az  = ('a'..'z').to_a
azz ={|e| [e, az.index(e)+2]}


Posted 2011-01-15T01:34:34.580

Reputation: 6 540

Why the hate? It is a functioning way of doing this AND I even say that is is a silly way to achieve the results. – Automatico – 2014-09-09T11:13:02.610

the call to #index means this is now an O(N^2) loop also why the +2 ? :) – rogerdpack – 2017-03-13T16:40:57.453

1As I write A fun, but useless way. +2 is to create the output the OP asks for – Automatico – 2017-03-13T18:04:42.773