2013-09-30 35 views
0

我試圖用這個方法返回與/奇數元素無遮擋

def odd_elements(array) 
    retArr = Array.new 
    array.each_with_index do |item, index| 
    if block_given? 
     yield(item) 
    else 
     retArr << item 
    end if index % 2 != 0 
    end 

    return retArr 
end 

,這樣我可以通過這兩個測試

it "should yield odd elements" do 
    res = odd_elements([1,2,3,4,5,6]) 
    res.should be_an_instance_of Array 
    res.should have(3).items 
    res.should include(2) 
    res.should include(4) 
    res.should include(6) 
end 

it "should yield" do 
    res = odd_elements([1,2,3,4,5,6]) {|x| x**2 } 
    res.should be_an_instance_of Array 
    res.should have(3).items 
    res[0].should == 4 
    res[1].should == 16 
    res[2].should == 36 
end 

返回奇數元素,但我在衰竭第二個。看來我不明白如何屈服,而我在兩個小時內嘗試了很多不同的事情並沒有做到。你能解釋一下爲什麼它不起作用嗎?

回答

1

yield返回你似乎要添加到retArr值:

def odd_elements(array) 
    retArr = [] 
    array.each_with_index do |item, index| 
    retArr << (block_given? ? yield(item) : item) if index % 2 != 0 
    end 
    retArr 
end 

我個人比較喜歡Enumerator(如果你有關於Ruby 1.9.3+),慢一點,但更易讀和靈活:

def odd_elements(array) 
    Enumerator.new do |e| 
    odd = false 
    array.each do |x| 
     e << x if odd 
     odd = ! odd 
    end 
    end 
end 

a = [1,2,3,4] 

odd_elements(a).to_a #=> [2, 4] 
odd_elements(a).map { |x| x * 2 } #=> [4, 8] 
1
odd_elements([1,2,3,4,5,6]){|x|p x**2 } #note the p 
#=> 4 
#=> 16 
#=> 36 

它很好,但你永遠不會將結果存儲在數組中。

odd_elements([1,2,3,4,5,6]).map {|x| x**2 } 

會將結果保存在數組中。

+0

有沒有辦法如何做到這一點在方法方面而不是測試方? –

+1

@OndrejJanacek我認爲你可以將'yield(item)'行改爲'retArr << yield(item)'。 –

+0

@Ondrej標準模式是:如果存在塊(忽略可能的大數組),則返回yield項;如果沒有塊,則返回一個數組。 – steenslag