2011-12-22 137 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