How to act differently on the first iteration in a Ruby loop?

Ruby

Ruby Problem Overview


I always use a counter to check for the first item (i==0) in a loop:

i = 0
my_array.each do |item|
  if i==0
    # do something with the first item
  end
  # common stuff
  i += 1
end

Is there a more elegant way to do this (perhaps a method)?

Ruby Solutions


Solution 1 - Ruby

You can do this:

my_array.each_with_index do |item, index|
    if index == 0
        # do something with the first item
    end
    # common stuff
end

Try it on ideone.

Solution 2 - Ruby

Using each_with_index, as others have described, would work fine, but for the sake of variety here is another approach.

If you want to do something specific for the first element only and something general for all elements including the first, you could do:

# do something with my_array[0] or my_array.first
my_array.each do |e| 
  # do the same general thing to all elements 
end

But if you want to not do the general thing with the first element you could do:

# do something with my_array[0] or my_array.first
my_array.drop(1).each do |e| 
  # do the same general thing to all elements except the first 
end

Solution 3 - Ruby

Arrays have an "each_with_index" method which is handy for this situation:

my_array.each_with_index do |item, i|
  item.do_something if i==0
  #common stuff
end

Solution 4 - Ruby

What fits best is depending on the situation.

Another option (if you know your array is not empty):

# treat the first element (my_array.first)
my_array.each do | item |
   # do the common_stuff
end

Solution 5 - Ruby

each_with_index from Enumerable (Enumerable is already mixed in with Array, so you can call it on an array without any trouble):

irb(main):001:0> nums = (1..10).to_a
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
irb(main):003:0> nums.each_with_index do |num, idx|
irb(main):004:1* if idx == 0
irb(main):005:2> puts "At index #{idx}, the number is #{num}."
irb(main):006:2> end
irb(main):007:1> end
At index 0, the number is 1.
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Solution 6 - Ruby

If you don't need the array afterwards:

ar = %w(reversed hello world)

puts ar.shift.upcase
ar.each{|item| puts item.reverse}

#=>REVERSED
#=>olleh
#=>dlrow

Solution 7 - Ruby

Ruby's Enumerable#inject provides an argument that can be used for doing something differently on the first iteration of a loop:

> l=[1,2,3,4]
=> [1, 2, 3, 4]
> l.inject(0) {|sum, elem| sum+elem}
=> 10

The argument is not strictly necessary for common things like sums and products:

> l.inject {|sum, elem| sum+elem}
=> 10

But when you want to do something different on the first iteration, that argument might be useful to you:

> puts fruits.inject("I like to eat: ") {|acc, elem| acc << elem << " "}
I like to eat: apples pears peaches plums oranges 
=> nil

Solution 8 - Ruby

Here's a solution that doesn't need to be in an immediately enclosing loop and avoids the redundancy of specifying a status placeholder more than once unless you really need to.

do_this if ($first_time_only ||= [true]).shift

Its scope matches the holder: $first_time_only will be globally once; @first_time_only will be once for the instance, and first_time_only will be once for the current scope.

If you want the first several times, etc, you can easily put [1,2,3] if you need to distinguish which of the first iterations you're in, or even something fancy [1, false, 3, 4] if you need something weird.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPanagiotis PanagiView Question on Stackoverflow
Solution 1 - RubydetunizedView Answer on Stackoverflow
Solution 2 - RubyRussellView Answer on Stackoverflow
Solution 3 - RubyToby HedeView Answer on Stackoverflow
Solution 4 - Rubyundur_gongorView Answer on Stackoverflow
Solution 5 - RubyTelemachusView Answer on Stackoverflow
Solution 6 - RubysteenslagView Answer on Stackoverflow
Solution 7 - RubysarnoldView Answer on Stackoverflow
Solution 8 - Rubyandroid.weaselView Answer on Stackoverflow