Ruby Each_With_Index Offset

Ruby each_with_index offset

Actually, Enumerator#with_index receives offset as an optional parameter:

[:foo, :bar, :baz].to_enum.with_index(1).each do |elem, i|
puts "#{i}: #{elem}"
end

outputs:

1: foo
2: bar
3: baz

BTW, I think it is there only in 1.9.2.

Ruby 1.8.7 each_with_index index offset

try this:

collection[4..-1].each_with_index do |element, index|
#do smth
end

this example will start from fifth element.

Ruby - each starting offset

Another, possibly more direct and readable possibility is to use Array#drop:

a.drop(3).each do |i|
# do something with item i
end

Now this really shines if combined with other methods inherited from Enumerable, so chances are there's a better alternative to your imperative each loop. Say you want to filter the extracted slice and transform it afterwards:

a = [0,1,2,3,4,5,6,7]
a.drop(3).select(&:even?).map { |x| x * 2 }
# => [8, 12]

Or say you want to print a list of all the values:

a = ["1", "2", "3", "4", "5"]
puts a.drop(3).join("\n")

Output:

4
5

These features inherited from functional programming are what makes Ruby so strong :)

using each_with_index and adding values with corresponding index for a new array

You can use map to accually return the results:

def add_value_and_index(array)
array.map.with_index { |value, index| value + index }
end

If the curriculum isn't using map yet, you can create a new array and add the sums to that in each iteration:

def add_value_and_index(array)
result = []
array.each_with_index { |value, index| result << value + index }
result
end

I would not use that second example in production, since it is verbose and hard to read.

How to map/collect with index in Ruby?

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:

arr.each_with_index.map { |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] }

Iterate through an array using each_with_index without a separate index variable

You can do:

diag1, diag2 = board.map.with_index {|row, i| [row[i],row[-i-1]]}.transpose

The main trick I'm using here is array's way of interpret negative argument. array[-1] always means the last element of an array, array[-2] denotes second last etc.

Ruby : Choosing between each, map, inject, each_with_index and each_with_object

A more tl;dr answer:

How to choose between each, map, inject, each_with_index and each_with_object?

  • Use #each when you want "generic" iteration and don't care about the result. Example - you have numbers, you want to print the absolute value of each individual number:

    numbers.each { |number| puts number.abs }
  • Use #map when you want a new list, where each element is somehow formed by transforming the original elements. Example - you have numbers, you want to get their squares:

    numbers.map { |number| number ** 2 }
  • Use #inject when you want to somehow reduce the entire list to one single value. Example - you have numbers, you want to get their sum:

    numbers.inject(&:+)
  • Use #each_with_index in the same situation as #each, except you also want the index with each element:

    numbers.each_with_index { |number, index| puts "Number #{number} is on #{index} position" }
  • Uses for #each_with_object are more limited. The most common case is if you need something similar to #inject, but want a new collection (as opposed to singular value), which is not a direct mapping of the original. Example - number histogram (frequencies):

    numbers.each_with_object({}) { |number, histogram| histogram[number] = histogram[number].to_i.next }


Related Topics



Leave a reply



Submit