Как действовать по-другому на первой итерации в цикле 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
есть ли более элегантный способ сделать это (возможно, способ)?
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