3

我想简化在多个条件适用时执行单个操作的代码。这是一个简化的示例:

case button
when 'up', 'upper-right', 'right', 'lower-right', 'down', 'lower-left', 'left', 'upper-left' 
  move_direction(button)
else
  do_something_else
end

如果我可以将这些选项封装成类或常量之类的东西,那会很有帮助,但我不确定如何做到这一点,或者是否可能。如何封装这些条件?

4

6 回答 6

7

您可以只使用数组 splat。

VALID_DIRECTION = %w( upper-left up upper-right left right
  lower-right down lower-left )

case button
when *VALID_DIRECTION
  move_direction(button)
else
  do_something_else
end
于 2013-08-14T05:26:53.180 回答
4

不太确定你在找什么,但也许是这样的?

class CaseMatchingArray < Array
  def ===(element)
    self.include?(element)
  end
end

direction = CaseMatchingArray.new([
    'up', 'upper-right', 'right', 'lower-right',
    'down', 'lower-left', 'left', 'upper-left'])

case 'up'
when direction
  puts "Yup, it's a direction"
end

请记住,Rubycase语句应用了===运算符,您可以通过匹配实现它的事物来进行任何您希望的测试。如果您还记得它Proc===作为调用实现,您可以这样做:

direction = lambda { |x|
  [
    'up', 'upper-right', 'right', 'lower-right',
    'down', 'lower-left', 'left', 'upper-left'
  ].include?(x)
}

并具有相同的结果,而无需定义类。或者你甚至可以在一个单例中做到这一点:

direction = [
    'up', 'upper-right', 'right', 'lower-right',
    'down', 'lower-left', 'left', 'upper-left'
]
def direction.===(other)
  self.include?(other)
end

编辑:或者 Chuck 所说的 :) 虽然,实现定义===的对象更通用,不仅限于数组的成员资格。

于 2013-08-14T05:02:10.230 回答
3

下面的解决方案并不是特别复杂,但可以说它比原始案例语句更具可读性。

def is_navigatable?(button)
  ['up', 
   'upper-right', 
   'right', 
   'lower-right', 
   'down', 
   'lower-left', 
   'left', 
   'upper-left'
  ].member? button
end

def main_method
  if is_navigatable? button
    move_direction button 
  else
    do_something_else
  end
end
于 2013-08-14T05:03:06.193 回答
1

如果我可以将这些选项封装成类或常量之类的东西,那会很有帮助,但我不确定如何做到这一点,或者是否可能。如何封装这些条件?

为什么不简单地重构该代码以删除case-while条件并简单地使用if-else(因为您似乎没有使用其他选项):

OPTIONS = 'up', 'upper-right', 'right', 'lower-right', 'down', 'lower-left', 'left', 'upper-left'

if OPTIONS.include? button
  move_direction(button)
else
  do_something_else
end
于 2013-08-14T06:47:05.003 回答
0

最快的方法是使用一套

require 'set'

def direction?(button)
  directions = Set[:up, 
                   :'upper-right', 
                   :right, 
                   :'lower-right', 
                   :down, 
                   :'lower-left', 
                   :left, 
                   :'upper-left']
  directions.include?(button)
end

button = 'up'
puts direction?(button.to_sym) #true
于 2013-08-14T08:07:08.277 回答
0

在您的特定情况下,您也可以这样做:

case button
when "up", "down", /\A(?:upper-|lower-|)(?:right|left)\z/
  move_direction(button)
else
  do_something_else
end
于 2013-08-14T10:33:25.130 回答