Ответ 1
Вы можете сделать это:
my_array.each_with_index do |item, index|
if index == 0
# do something with the first item
end
# common stuff
end
Попробуйте на ideone.
Я всегда использую счетчик для проверки первого элемента (i==0
) в цикле:
i = 0
my_array.each do |item|
if i==0
# do something with the first item
end
# common stuff
i += 1
end
Есть ли более элегантный способ сделать это (возможно, метод)?
Вы можете сделать это:
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
from 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
Ruby 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]
, если вам нужно что-то странное.