在Ruby循环中第一次做一些特别的事情

时间:2009-10-08 02:22:14

标签: ruby

假设我有一个这样的循环:

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

Ruby有没有办法写if FIRST_TIME_AROUND?我依旧回忆起曾经读过一些关于此的事情,但我不记得了。

编辑:我确实知道(很多)这样做的标准方法......我追求的是最优雅的解决方案。

8 个答案:

答案 0 :(得分:11)

items.each_with_index do |x, i|
  do_something if i==0
  do_rest
end

答案 1 :(得分:5)

do_something
items.drop(1).each do |x|
  do_rest
end

答案 2 :(得分:2)

最优雅的方法是尽可能在循环外做一次性的事情。

答案 3 :(得分:0)

有一种丑陋的,通用的方式,并非特定于Ruby:

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

这种逻辑是丑陋的,冗长的,但在大多数语言中都有效。

答案 4 :(得分:0)

我创建了一个小实用程序扩展来处理这种情况。扩展有点难看,但它确实在其他地方制作更整洁的代码。

它允许您编写如下代码:

    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

在某处添加:

#
# 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

答案 5 :(得分:0)

do_something items.first
items.each do |item|
  do_something_else item
end

答案 6 :(得分:0)

我的建议:

items.first # do something

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

原因:

  • 在循环中放置 if 是未经优化的。
  • 我相信这是执行时间和使用内存的最优化答案。

答案 7 :(得分:0)

这是一个如何在视图中执行此操作的示例,用于围绕某些元素生成div:

<% @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 %>

输出:

<div>
  <span class="label label-warning">AAA</span>
  <span class="label label-warning">ADA</span>
  <span class="label label-warning">ABA</span>
</div>