2011-12-22 130 views
1

我有三個值(foo,bar,bad),並基於哪一個值傳遞給我想要使用另外兩個值的函數。我可以避免if-elsif-else在這個ruby函數中嗎?

例如,調用self.method(foo)會導致類似的情況,foo未定義。

def method 
    self.foo = 180 - self.bar - self.bad 
end 

我可以做一個簡單的if-elsif-else設置,但是有沒有更好的(更習慣的)方法?

更新爲清楚:

這裏有一個建議,可能看起來像在生產:通過@triangle.solve_angles(self.C)甚至「叫

def solve_angles(missing) 
    angles = 180 - [ A, B, C ].reject { |e| e == missing }.inject(:+) 
end 

@ triangle.solve_angles( 「C」)將成爲可能。

+0

這完全取決於;是基於價值的決定,還是字面上依賴於符號? – 2011-12-22 16:44:06

+0

它總是有助於展示您爲此編寫的內容,而不是讓我們其他人嘗試將代碼可視化並對其進行改進。 – 2011-12-22 16:46:57

+0

我已經更新了代碼,希望更有意義。它基本上是試圖解決三個角度,當兩個已知和第三個失蹤,但所有三個必須加起來180. – 2011-12-22 16:48:58

回答

0

你不需要指定你正在求解的角度;它隱含在問題的定義中。如果你開始像這樣的東西(任何類似的錯誤處理省略掉):

class Triangle 
    def initialize h 
    h.keys.each { |key| instance_variable_set "@#{key}".to_sym, h[key] } 
    end 

    def to_s 
    "a=#{@a}, b=#{@b}, c=#{@c}" 
    end 

    def solve 
    angle = instance_variables.inject(180) { |v, a| v -= instance_variable_get(a) } 
    [:@a, :@b, :@c].each {|s| instance_variable_set(s, angle) unless instance_variable_defined? s } 
    self 
    end 
end 

然後:

pry(main)> t = Triangle.new :a => 20, :c => 30 
=> a=20, b=, c=30 
pry(main)> t.solve 
=> a=20, b=130, c=30 
pry(main)> 

你也可以返回/指示哪個角度實際上是解決了,如果需要的話。

這實際上並不是避免if聲明,這是您的具體問題。它不需要明確地拼出它們中的每一個,我將其作爲問題的意圖。

如果你真的需要「解決」,你可以做補充:

def solve_for sym 
    solve 
    instance_variable_get("@#{sym}".to_sym) 
end 

從技術上講,你能解決只能確定值未設置,但MEH後。

> t = Triangle.new :a => 20, :c => 30 
=> a=20, b=, c=30 
> t.solve_for :b 
=> 130 
> t 
=> a=20, b=130, c=30 
> t = Triangle.new :a => 20, :c => 30 
=> a=20, b=, c=30 
> t.solve_for :a 
=> 20 
> t 
=> a=20, b=130, c=30 
+0

這裏有幾件事我不太明白他們是如何工作的。感謝所有這些。我會玩弄它,以確保我瞭解它是如何工作的。我很欣賞你投入的時間。 – 2011-12-22 17:39:31

0

如果它只是基本的加法,乘法等,那麼以下就足夠了,但任何更復雜的不能保證。

def method(input) 
    self.foo + self.bar + self.bad - input 
end 

或者,您可以將它們全部放入數組中,並刪除您提供的數組。

def method(input) 
    [self.foo, self.bar, self.bad].reject { |e| e==input }.inject { ... } 
end 
+2

請注意'delete'返回刪除的元素(或'nil'),所以第二個代碼段不起作用。 – 2011-12-22 16:54:01

+1

已更新。感謝您的支持。 – Matt 2011-12-22 17:02:04

0

嘗試somethng這樣的:

def method(arg) 
    [ bar, bad, foo ].reject { |e| e == arg }.inject(:+) 
end 

請注意,你不給self接收器,它是隱含的。

+0

我已經在上面添加了一些說明。我想我正在接近這個錯誤的方式。 – 2011-12-22 16:58:21

0

這裏是我想出瞭解決方案:

def solve_angles(missing) 
     holder = [:A, :B, :C] 
     holder.delete(missing) 
     angle = 180 - (self.send(holder[0]) + self.send(holder[1])) 
end 

這是一個壞的解決方案?爲什麼?

或者,這是更清潔/更好?

def solve_angles(missing) 
    holder = [:A, :B, :C] - [missing] 
    angle = 180 - send(holder[0]) - send(holder[1]) 
end 

或者:

def solve_angles(missing) 
    angles = [:A, :B, :C] - [missing] 
    angles.inject(180) { |memo, a| memo - send(a) } 
end 
+0

我不會把它稱爲「壞」,如果你有'attr_accessor's,它似乎可以正常工作。將編輯附加到您的答案。 – 2011-12-22 18:18:41

+0

我傾向於使用更通用的解決方案(而不是明確地指出三方)的一個原因是,它適用於其他形狀,可以在運行時定義,填充,查詢等。例如,'s = Shape.new(sides:5)'可以完成創建五邊形所需的所有設置,包括計算內角總和,創建角度訪問器等。 – 2011-12-22 18:27:06

相關問題