2011-11-18 82 views
60

我總是用一個計數器在一個循環來檢查的第一項(i==0):如何在Ruby循環的第一次迭代中採取不同的行爲?

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

有沒有更優雅的方式來做到這一點(可能是一個方法)?

+7

爲什麼會有人投票關閉這個?這是一個非常真實的問題。 – Telemachus

+1

什麼阻止你在這種情況下做你所需要的數組中的第一項,然後做一個普通的'each'循環,只是常見的東西? – Russell

+0

@Russell如果他對第一項(比如'array.first或array [0]')做特殊的事情,然後運行'each'循環,他將*必須測試第一個項目如果他*不希望對第一個項目做常規的事情。 – Telemachus

回答

62

你可以這樣做:

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

試試它ideone

+0

我認爲這可能不是最好的答案 - 它基本上是OP在他的問題中寫的,但是使用'.each_with_index'而不是'.each'。下面的'.drop(1)'建議似乎更像ruby-like,完全避免了索引。 – jm3

2

Enumerableeach_with_index(可枚舉已與陣列混合,這樣你就可以把它叫做一個陣列上沒有任何問題):

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] 
3

陣列有一個「each_with_index」方法,它是非常方便的這種情況:

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

當你想呈現不同的東西時,這對於在視圖中循環對象的經典情況非常方便。非常感謝! – Apollo

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 
+0

因爲'inject'是整潔而可愛的,我不認爲它回答了OP的問題 - 這是如何爲循環的第一次迭代做些不同的事情。 – Russell

+0

我不'注入'符合他所問的,但也許你看到我們錯過的東西。他希望通過一個數組第一次做一些不同的事情。他的'i + = 1'是一個手動計數器,而不是一個總和。 – Telemachus

+0

@魯塞爾,哈!我必須寫一些關於'注入'的信息,並忘記了第一次迭代時論點的全部內容都做了不同的事情。謝謝。 – sarnold

37

使用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 
+0

+1我有同樣的想法。唯一的區別是數組爲空時。 –

+10

我喜歡'my_array.drop(1)'它更具說明性。 – tokland

+1

這些工作,但不是在特殊行爲處於循環中的情況。在這種情況下,我希望你需要做each_with_index作爲最可讀的解決方案。 –

3

最適合什麼取決於具體情況。

另一種選擇(如果你知道你的數組不爲空):

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

如果您不需要事後陣列:

ar = %w(reversed hello world) 

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

#=>REVERSED 
#=>olleh 
#=>dlrow 
+0

與問題中的代碼相反,您並沒有扭轉第一個單詞。 –

+0

是的,一定在某個地方想到了一個'else'。但它確實做了問題的標題。 – steenslag

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]如果你需要奇怪的東西。

相關問題