我可以在这个ruby函数中避免if-elsif-else吗?

时间:2011-12-22 16:39:50

标签: ruby if-statement control-flow

我有三个值(foo,bar,bad),并根据我传递给函数的哪一个我想要使用另外两个。

例如,调用self.method(foo)会导致类似foo未定义。

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

我可以使用简单的if-elsif-else设置来实现,但是有更好的(更惯用的)方法吗?

为清晰起见而更新:

以下是生产中的一个建议:

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

通过@triangle.solve_angles(self.C)或甚至'@ triangle.solve_angles(“C”)调用是可能的。

4 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

尝试这样的事情:

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

请注意,您不是self接收者,而是隐含的。

答案 2 :(得分: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

答案 3 :(得分: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