2017-07-28 69 views
1

如何编写一个方法来有效地实现这个功能?Ruby如何编写连续的分区

divide_array([a,b,c]) # return a.to_f/b.to_f/c.to_f 
divide_array([a,b,c,d,e]) # return a.to_f/b.to_f/c.to_f/d.to_f/d.to_f 

这是我能像

def divide_array(array) 
    return false if array.include?(0) 
    result = 0 
    array.each_with_index do |i, index| 
    break if index >= array.size - 1 
    result = i.to_f/array[index + 1].to_f 
    end 

    result 
end 

但我认为Ruby是一个优雅的语言,它必须是一个更好和更有效的方式来实现这一目标。 (也许就像reduceinject?)

+0

你的问题,如果你的例子会比较清楚((52/2)/ 4)/ 2 =>((26.0)/ 4)/ 2 => 6.5/2 = > 3.25'。 –

+0

@CarySwoveland我删除了我的评论。我实际上是参考了这个风格指南,并且完全得到了向''inject''后面的'reduce'。谢谢你指出。 – Dbz

回答

8

注入(或减少),实际上,但是to_f和划分可以一次完成fdiv

[3,2,1].inject(:fdiv) #=> 1.5 

更精确的是转换为Rational,并且只能尽可能晚地转换为Float。演示:

[3,5,6].map(&:to_f).inject(:/) # => 0.09999999999999999 
[3,5,6].map(&:to_r).inject(:/).to_f # => 0.1 

由于sagarpandya82意见(新对我来说),这种转换到Rational和分裂也可以在一气呵成完成的,在达到高潮:

[3,5,6].inject(:quo).to_f #=> 0.1 
+3

我的工具包的另一种方法('fdiv')。很高兴知道。 –

+1

你的意思是在你的第一句话中是'to_f'? –

+0

@ sagarpandya82啊,是的,谢谢。 – steenslag

5

这里有一个优雅的方式来做到这一点:

[3,2,1].map(&:to_f).reduce(:/) 
# => 1.5 

没有PROC速记写同样的事情:

[3,2,1].reduce { |quotient, el| quotient.to_f/el.to_f } 
+1

最好让读者决定什么是“优雅”。首先,其他人(如此处)可能会发布更优雅的答案。 :-)。它仍然值得我的赞赏。 –

+0

我相信第二个答案更好,因为它跳过了O(n)操作的列表。虽然这两种解决方案都是O(n),但第二种解决方案的实际优化可能在具有巨大阵列的实际场景中非常重要。 – Dbz