Сделайте что-то особенное в первый раз в цикле Ruby - PullRequest
1 голос
/ 08 октября 2009

Допустим, у меня есть такой цикл:

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

есть ли способ в Ruby написать if FIRST_TIME_AROUND? Я смутно припоминаю, что когда-то читал что-то об этом, но не могу вспомнить.

РЕДАКТИРОВАТЬ: Я знаю о (многих) стандартных способов сделать это ... Я после наиболее элегантного решения возможно.

Ответы [ 8 ]

11 голосов
/ 08 октября 2009
items.each_with_index do |x, i|
  do_something if i==0
  do_rest
end
5 голосов
/ 16 сентября 2011
do_something
items.drop(1).each do |x|
  do_rest
end
2 голосов
/ 08 октября 2009

Самый элегантный способ - это сделать разовую вещь вне цикла, если это вообще возможно.

0 голосов
/ 14 февраля 2016

Вот пример того, как сделать это в представлении для создания 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>
0 голосов
/ 21 мая 2012

Мое предложение:

items.first # do something

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

Причины:

  • Помещение , если внутри цикла, не оптимизировано.
  • Я считаю, что это наиболее оптимизированный ответ для времени выполнения и используемой памяти.
0 голосов
/ 16 сентября 2011
do_something items.first
items.each do |item|
  do_something_else item
end
0 голосов
/ 28 февраля 2010

Я создал небольшое расширение утилиты, чтобы справиться с этой ситуацией. Расширение немного уродливо, но оно делает код более понятным везде.

Позволяет написать код, подобный:

    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
0 голосов
/ 08 октября 2009

Есть отвратительный, общий способ, не специфичный для Ruby:

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

Такая логика уродлива, многословна, но работает в большинстве языков.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...