39

In your typical each loop in Rails, how do I determine the last object, because I want to do something different to it than the rest of the objects.

<% @stuff.each do |thing| %>

<% end %>
alamodey
  • 13,682
  • 22
  • 84
  • 109

5 Answers5

66
@stuff.each do |s|
  ...normal stuff...
  if s == @stuff.last
    ...special stuff...
  end
end
abject_error
  • 2,730
  • 16
  • 22
  • 2
    this is the best answer... could be a touch better if you'd like to 1-line it. `s == @stuff.last ? 'thing for last' : 'things for the rest'` – Dudo Oct 01 '13 at 01:34
  • 15
    warning: this won't work if @stuff elements aren't unique. ie "a = [1,1];a.map{|v| v == a.last}" returns [true,true]. in case of integers there's no way to determine if it's really last element. if using other objects, you can use equal? (http://stackoverflow.com/questions/7156955/whats-the-difference-between-equal-eql-and) – Pavel K. Dec 03 '13 at 15:11
33

Interesting question. Use an each_with_index.

len = @stuff.length

@stuff.each_with_index do |x, index|
 # should be index + 1       
 if index+1 == len
 # do something
  end
end
Jakub Kuchar
  • 1,646
  • 2
  • 22
  • 38
A.Ali
  • 755
  • 6
  • 14
8
<% @stuff[0...-1].each do |thing| %>
  <%= thing %>
<% end %>
<%= @stuff.last %>
jackpipe
  • 911
  • 1
  • 8
  • 13
  • Much nicer than checking every iteration if we're at the end! Although I think you have one too many `.`'s? – Matt Aug 31 '16 at 14:06
  • Thanks! Actually it's a little confusing, since `-1` in a range stands for "the last element", so actually `stuff[0..-1] == stuff`. We need to use the `...` form of range which omits the last element. – jackpipe Jan 12 '17 at 06:48
  • I see! You should add that to the answer to make it a bit clearer and save stupid questions like mine ;) – Matt Jan 12 '17 at 14:48
2

A somewhat naive way to handle it, but:

<% @stuff.each_with_index do |thing, i| %>
  <% if (i + 1) == @stuff.length %>
    ...
  <% else %>
    ...
  <% end %>
<% end %>
apostlion
  • 720
  • 5
  • 10
2

A more lispy alternative is to be to use

@stuff[1..-1].each do |thing|

end
@stuff[-1].do_something_else
Sam
  • 1,014
  • 6
  • 8