Do something special for the first time in a Ruby loop

Say I have a loop like this:

items.each do |x| if FIRST_TIME_AROUND # do something end # do the rest of stuff end 

Is there a way in Ruby to write if FIRST_TIME_AROUND ? I vaguely recall something about this, but I cannot remember.

EDIT: I know about (many) standard ways to do this ... I am after the most elegant solution.

+1
ruby
Oct 08 '09 at 2:22
source share
8 answers
 items.each_with_index do |x, i| do_something if i==0 do_rest end 
+11
Oct 08 '09 at 2:27
source share
 do_something items.drop(1).each do |x| do_rest end 
+5
Sep 16 2018-11-11T00:
source share

The most elegant way is to do a one-time thing off-cycle, if at all possible.

+2
Oct 08 '09 at 4:11
source share

There's an ugly, general way that Ruby doesn't have:

 first = true items.each do |x| if first first = false # do something end # do the rest of stuff end 

This logic is ugly, verbose, but works in most languages.

0
Oct 08 '09 at 2:26
source share

I created a small service extension to handle this situation. The extension is a little ugly, but it does for cleaner code everywhere.

It allows you to write code like:

  nodes.each_position do |position| position.first do |first_node| # Do stuff on just the first node end position.all do |node| # Do stuff on all the nodes end position.last do |last_node| # Do some extra stuff on the last node end end 

Add this somewhere:

 # # Extends enumerable to give us a function each_index # This returns an Index class which will test if we are the first or last # or so item in the list # Allows us to perform operations on only selected positions of an enumerable. # module Enumerable class Index attr_accessor :index attr_accessor :object def initialize(count) @index = 0 @count = count @object = nil end def first if @index == 0 yield(@object) end end def not_first if @index != 0 yield(@object) end end def last if @index == @count - 1 yield(@object) end end def not_last if @index != @count - 1 yield(@object) end end def all yield(@object) end def index(idx) if @index == idx yield(@object) end end end # Add the method to enumerables. # Iterates through the list. For each element it creates an Index instance # and passes it the index of the iteration, the length of our list and the # object at the index. # def each_position count = 0 index = Index.new(self.length) self.each do |obj| index.index = count index.object = obj yield index count += 1 end end end 
0
Feb 28 '10 at 2:33
source share
 do_something items.first items.each do |item| do_something_else item end 
0
Sep 16 '11 at 12:30
source share

My suggestion:

 items.first # do something items[1..items.count-1].each do |item| do_whatever end 

Causes:

  • The if insert inside the loop is not optimized.
  • I believe this is the most optimized answer for runtime and memory usage.
0
May 21 '12 at 10:53
source share

Here is an example of how to do this in a view to create a div around some elements:

 <% @provider.organizations.each_with_index do |organization, i| %> <% if i == 0 %> <div> <% end %> <span class="label label-warning"><%= organization.name %></span> <% if i == @provider.organizations.count - 1 %> </div> <% end %> <% end %> 

Output:

 <div> <span class="label label-warning">AAA</span> <span class="label label-warning">ADA</span> <span class="label label-warning">ABA</span> </div> 
0
Feb 14 '16 at 1:49 on
source share



All Articles