如何在Ruby循环中的第一次迭代中采取不同的行为?

时间:2011-11-18 11:05:44

标签: 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 个答案:

答案 0 :(得分:70)

你可以这样做:

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

ideone上试用。

答案 1 :(得分:44)

正如其他人所描述的,使用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

答案 2 :(得分:3)

数组有一个“each_with_index”方法,对于这种情况很方便:

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

答案 3 :(得分:3)

最适合的情况取决于具体情况。

另一个选项(如果您知道您的数组不为空):

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

答案 4 :(得分:2)

来自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]

答案 5 :(得分:2)

如果之后不需要数组:

ar = %w(reversed hello world)

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

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

答案 6 :(得分:1)

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

答案 7 :(得分:0)

这是一个不需要在一个封闭的循环中的解决方案,并且避免了多次指定状态占位符的冗余,除非你真的需要。

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

其范围与持有人匹配:$first_time_only将全局一次; @first_time_only将为实例一次,first_time_only将为当前范围一次。

如果您想要前几次等,如果您需要区分哪些首次迭代,或者如果您需要某些内容,则可以轻松放置[1,2,3] [1, false, 3, 4]怪异。