2013-09-30 39 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