如何在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 

有没有更优雅的方式来做到这一点(也许是一种方法)?

你可以这样做:

 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 

Enumerable中的 each_with_index (Enumerable已经和Array混合在一起了,所以你可以在数组上调用它):

 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 

这是一个解决scheme,不需要立即封闭循环,避免了多次指定状态占位符的冗余,除非您确实需要。

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

它的范围匹配持有者: $first_time_only将在全球范围内一次; 对于实例, @first_time_only将是一次, @first_time_only对于当前作用域将是一次。

如果你想要前几次等,你可以很容易地把[1,2,3]如果你需要区分你的第一次迭代,甚至是什么幻想[1, false, 3, 4]如果你需要奇怪的东西。