2

Dev Bootcamp 的工作前练习之一是 RPN 计算器。我让它工作,但想重构反馈。非常感谢任何使此代码更清晰的帮助。

class RPNCalculator
  def evaluate(rpn)
    a = rpn.split(' ')
    array = a.inject([]) do |array, i|    
      if i =~ /\d+/ 
        array << i.to_i
      else
        b = array.pop(2)
        case 
          when i == "+" then array << b[0] + b[1]  
          when i == '-' then array << b[0] - b[1]  
          when i == '*' then array << b[0] * b[1]  
          when i == '/' then array << b[0] / b[1]  
        end
      end
    end
    p array.pop
  end
end

calc = RPNCalculator.new
calc.evaluate('1 2 +')   # => 3
calc.evaluate('2 5 *')   # => 10
calc.evaluate('50 20 -') # => 30
calc.evaluate('70 10 4 + 5 * -') # => 0  
4

2 回答 2

2
class RPNCalculator
  def evaluate rpn
    array = rpn.split(" ").inject([]) do |array, i|    
      if i =~ /\d+/ 
        array << i.to_i
      else
        b = array.pop(2)
        array << b[0].send(i, b[1])
      end
    end
    p array.pop
  end
end
于 2013-07-02T08:34:21.447 回答
1

我倾向于避免case..when使用查找表。所以我会将您的代码更改为:

class RPNCalculator
  def evaluate(rpn)
    a = rpn.split(' ')
    array = a.inject([]) do |array, i|    
      if i =~ /\d+/ 
        array << i.to_i
      else
        array << array.pop(2).reduce(op(i))
      end
    end
    p array.pop
  end

  private

  def op(char)
    {'+'=>:+, '-'=>:-, '/'=>:/, '*'=>:*}[char]
  end
end

我也不相信你应该只弹出 2 个操作数。“1 2 3 +”将是有效的 RPN,计算结果为 6。应该减少整个堆栈。这也避免了突变,这是一件好事,因为它遵循更实用的风格。

class RPNCalculator
  def evaluate(rpn)
    a = rpn.split(' ')
    array = a.inject([]) do |array, i|    
      if i =~ /\d+/ 
        [*array, i.to_i]
      else
        [array.reduce(op(i))]
      end
    end
    p array.pop
  end

  private

  def op(char)
    {'+'=>:+, '-'=>:-, '/'=>:/, '*'=>:*}[char]
  end
end

我也在这里删除了另一个突变,通过使用[*arr, value]而不是实际修改数组。

最后,我会避免直接从您的#evaluate方法打印,而只返回数字。我也(再次)避免突变:

class RPNCalculator
  def evaluate(rpn)
    a = rpn.split(' ')
    stack = a.inject([]) do |stack, i|    
      if i =~ /\d+/ 
        [*stack, i.to_i]
      else
        [stack.reduce(op(i))]
      end
    end
    stack.last
  end

  private

  def op(char)
    {'+'=>:+, '-'=>:-, '/'=>:/, '*'=>:*}[char]
  end
end

我将 'array' 重命名为 'stack',因为它是一个解析器堆栈,并且比array.

于 2013-07-02T05:08:14.673 回答