【问题标题】:Can if statements be refactored to boolean operators like !=, ==, && and ||?是否可以将 if 语句重构为布尔运算符,例如 !=、==、&& 和 ||?
【发布时间】:2019-03-22 02:25:47
【问题描述】:

这可以重构为布尔值吗? board 是一个数组,move 是一个索引。如果board[move]" """nil,则position_taken?(board, move) 应该返回false,但如果board[move]"X""O",则返回true

def position_taken?(board, move)
  if board[move] == " "
    false
  elsif board[move] == ""
    false
  elsif board[move] == nil
    false
  else
    true
  end
end

【问题讨论】:

  • board[move] 是否保证等于 " """、nil、"X""O"?如果是这样,你可以!board[move].to_s.strip.empty?,但这是我不推荐的hack(它之所以有效,是因为nil.to_s #=> "")。如果board[move] 等于其他值,返回什么?
  • 是的。 board[move] 保证等于 " """、nil、"X""O",并且没有其他值。
  • 有了积极的支持,您可以使用board[move].present?

标签: ruby if-statement boolean refactoring


【解决方案1】:

因为你有更少和更简单的正面案例,我会测试相反的情况:

def position_taken?(board, move)
  %w[X O].include?(board[move])
end

它处理无效值的方式与原始方法不同,但它直接执行方法名称所暗示的操作:检查位置是否被占用(而不是检查位置是否未被占用)。

【讨论】:

    【解决方案2】:

    您可以使用none? 并通过board[move] 进行比较:

    [' ', '', nil].none?(nil) # false
    [' ', '', nil].none?('')  # false
    [' ', '', nil].none?(' ') # false
    [' ', '', nil].none?('t') # true
    

    【讨论】:

    • 不错。但我认为这种语法适用于 ruby​​ >= v2.5 .x ?
    • 是的!你说得对,它来自 2.5+。否则,它必须与块一起使用。
    【解决方案3】:

    如果不知道你将传递什么作为板参数,很难知道你的方法在做什么,所以我能演示的最好的只是一个字符串:

    str=''
    !!(str && !str.strip.empty?)
    #=> false
    
    str='a'
    !!(str && !str.strip.empty?)
    #=> true
    
    str='   '
    !!(str && !str.strip.empty?)
    #=> false
    
    str=' '
    !!(str && !str.strip.empty?)
    #=> false
    
    str=nil
    !!(str && !str.strip.empty?)
    #=> false
    

    【讨论】:

      【解决方案4】:

      我认为这在逻辑上是等价的:

      def position_taken?(board, move)
        !(board[move] == " " || board[move] == "" || board[move] == nil)
      end
      

      如果任何一个条件为真,则反转并返回假。如果所有条件都为假,则将其反转为真。


      您还可以将要匹配的字符串放在一个数组中并使用!include? 之类的内容,或者,如果您使用的是ActiveSupport,则可以使用exclude?

      def position_taken?(board, move)
        ["", " ", nil].exclude?(board[move])
      end
      

      【讨论】:

      • 内部对于字符串匹配是有意义的,但我们知道为 board 传递什么数据类型吗?
      • nil 需要比较吗?为什么不!board[move]
      • @lacostenycoder !board[move] 会起作用,但双重反转可能很难遵循。你也可以使用board[move].nil?
      • exclude? 是一个 active_support 方法。 !include? 可能在不使用 Rails 的情况下工作。
      【解决方案5】:

      如果只允许 X 或 O,为什么不在这样的条件中指定它们:

      boared[idx] == 'X' || board[idx] == 'O'
      

      我认为它的可读性和简单性要好得多。

      【讨论】:

        【解决方案6】:

        FWIW,这段代码应该重构为:

        def position_taken?(board, move)
          not board[move].to_s.strip.empty?
        end
        

        【讨论】:

        • 这可能无关紧要,但由于strip,这与原始代码的行为略有不同。例如," "(两个空格)将在原始代码中返回 true,但在此实现中返回 false
        • @ScottBartell 这是井字游戏; board[move].length == 1 总是正确的。
        • 哈哈,这很有意义......没有意识到这是井字游戏。
        【解决方案7】:

        找到了解决办法。可以重构为:

        def position_taken?(board, move)
          board[move] != " " && board[move] != ""
        end
        

        【讨论】:

        • 如果board[move]nil,则返回true
        【解决方案8】:
        def position_taken?(board, move)
          !case board[move]; when " ", "", nil; true end
        end
        

        【讨论】:

        • 您能否对此答案添加一些解释? From review.
        • 这只是一个否定的case-construction。没有什么特别要解释的。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-12-31
        • 2015-01-07
        • 2020-09-17
        • 1970-01-01
        • 1970-01-01
        • 2022-09-29
        • 2014-05-30
        相关资源
        最近更新 更多