2017-07-28 68 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