Как действовать по-другому на первой итерации в цикле Ruby?



Я всегда использую счетчик для проверки первого элемента (i==0) в цикле:



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


есть ли более элегантный способ сделать это (возможно, способ)?

410   8  

8 ответов:

вы можете сделать это:

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

попробовать ideone.

используя each_with_index, как другие описали, будет работать нормально, но ради разнообразия здесь другой подход.

Если вы хотите сделать что-то конкретное только для первого элемента и что-то общее для всех элементов, включая первый, вы можете сделать:

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

но если вы не хотите делать общую вещь с первым элементом, который вы могли бы сделать:

# 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

массивы имеют метод" each_with_index", который удобен для этой ситуации:

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

то, что подходит лучше всего, зависит от ситуации.

другой вариант (если вы знаете, что Ваш массив не пуст):

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

each_with_index С перечисли (Enumerable уже смешивается с массивом, так что вы можете вызвать его на массив без каких-либо проблем):

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]

Если вам не нужен массив после:

ar = %w(reversed hello world)

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

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

Руби!--5-->Enumerable#inject предоставляет аргумент, который может быть использован для делать что-то по-другому на первой итерации цикла:

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

аргумент не является строго необходимым для обычных вещей, таких как суммы и продукты:

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

но когда вы хотите сделать что-то разные на первой итерации, этот аргумент может быть полезен для вас:

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

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

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

его объем соответствует держателю:$first_time_only будет как во всем мире; @first_time_only будет один раз для экземпляра, и first_time_only будет один раз для текущей области.

если вы хотите, чтобы первые несколько раз, и т. д., Вы можете легко положить [1,2,3] если вам нужно определить, какой из первых итерации, в которых вы находитесь, или даже что-то необычное [1, false, 3, 4] если вам нужно что-то странное.

Comments

    Ничего не найдено.