Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Ruby中的嵌套条件语句_Ruby On Rails_Ruby - Fatal编程技术网

Ruby on rails Ruby中的嵌套条件语句

Ruby on rails Ruby中的嵌套条件语句,ruby-on-rails,ruby,Ruby On Rails,Ruby,我的问题有两个: 我没有意识到我可以像这样嵌套多个条件。这看起来很恶心。我想我知道这里发生了什么,但是有人能解释一下,让我真正理解这个概念吗 由于我不太理解嵌套条件,我对重构有点迷茫,一开始我在这方面相当薄弱。请大家介绍一些可能的重构解决方案并加以解释,好吗?这将大大有助于我有限的理解 您可以通过更类似于Ruby的方式将其大幅缩减: def valid_triangle?(*sides) case (sides.length) when 3 sides.sort! s

我的问题有两个:

  • 我没有意识到我可以像这样嵌套多个条件。这看起来很恶心。我想我知道这里发生了什么,但是有人能解释一下,让我真正理解这个概念吗

  • 由于我不太理解嵌套条件,我对重构有点迷茫,一开始我在这方面相当薄弱。请大家介绍一些可能的重构解决方案并加以解释,好吗?这将大大有助于我有限的理解



  • 您可以通过更类似于Ruby的方式将其大幅缩减:

    def valid_triangle?(*sides)
      case (sides.length)
      when 3
        sides.sort!
    
        sides[0] + sides[1] >= sides[2]
      else
        false
      end
    end
    
    只要有可能,试着将您的逻辑表达为一系列数据转换,通常更容易理解。在这种情况下,将传入点视为一个数组并对其进行排序,而不是对每个点使用特殊的case逻辑。这种特殊情况下的代码总是很麻烦,很难测试,如果你犯了一个很小的错误,就很容易发生微妙的错误

    值得注意的是,在Ruby中,您的
    if
    语句的格式如下:

    if condition
      # ...
    elsif condition
      # ...
    else
      # ...
    end
    

    else
    后面紧跟着代码可能是有效的语法,但看起来很混乱。似乎您正在针对
    最大==b
    进行测试,并且犯了一个错误,无意中做了一个赋值,而实际上这是
    else
    块的内容,而不是
    难以捉摸的
    的条件

    此代码可以很容易地进行更新,以包括负长度的测试,例如添加
    边[0]>0
    作为逻辑的一部分


    另外,使用Ruby隐式
    return
    ,其中提供的最后一个值是从方法返回的值。
    case
    语句实际上传播了触发的值,这使得传递内容非常方便。

    在不涉及核心算法的情况下,下面是一些可以改进方法结构的方法

    def valid_triangle?(a, b, c, sum)
    
      # terminate early if inputs are not in expected state
      return false if [a,b,c].include? 0
    
        if a >= b
          largest = a
          sum += b
        else 
          largest = b
          sum += a
        end
    
        # space to separate this from the previous if/else block
        if c > largest
          sum += largest
          largest = c
        else 
          sum += c
        end
    
      # be consistent on return type (string or boolean)
      sum > largest
    
      # ternary if can be used if return type is not a boolean 
      # strings are not recommended for true/false values though
      # sum > largest ? "true" : "false"
    end
    
    嵌套条件句 实际上,嵌套条件句的概念与任何其他类型的条件句的概念没有太大区别。条件语句控制是否执行其中的所有代码。因此,如果将一个条件嵌套在另一个条件中,则外部条件将控制是否执行内部条件

    some_var = 5
    if some_var > 1
      # Code here will be executed
      if some_var > 10
        # Code here will not be executed
      end
    end
    
    if some_var > 10
      # Code here will not be executed
      # The following conditional won't be checked at all,
      # because execution won't reach this point.
      if some_var > 1
        # This won't be executed.
      end
    end
    # The execution point will immediately jump to here once
    # the some_var > 10 condition is determined to be false.
    
    重构代码 至于重构代码,这里有很多地方可以改进。首先,嵌套条件句通常可以而且应该避免。不是因为它们很难理解,而是因为通常有更可读的替代品

    例如,您的代码将整个方法封装在一个大条件中,该条件基本上表示“除非此条件为真,否则不要执行此方法的其余部分”:

    这可以通过在方法开头包含一个条件来避免,如果条件为false,该条件将立即返回:

    return false unless a != 0 || b != 0 || c != 0
    
    我注意到的另一件事是,在某些情况下,返回的是字符串而不是布尔值:

    if sum > largest
      return "true"
    else
      return "false"
    end
    
    这不是个好主意。返回一个实际的布尔值:

    if sum > largest
      return true
    else
      return false
    end
    
    但事实上,整个条件并不是那么有用<代码>求和>最大值在一种情况下计算为true,在另一种情况下计算为false,因此您可以:

    return sum > largest
    
    另外,为什么要将
    sum
    作为参数传入?这不应该总是从零开始吗?您可以从方法签名中删除该语句,只需在方法体中将sum初始化为0:

    sum = 0
    
    现在让我们看看您的代码是什么样子的:

    def valid_triangle?(a, b, c)
      return false unless a != 0 || b != 0 || c != 0
    
      sum = 0
    
      if a >= b
        largest = a
        sum += b
      else
        largest = b
        sum += a
      end
    
      if c > largest
        sum += largest
        largest = c
      else
        sum += c
      end
    
      return sum > largest
    end
    
    看起来好多了。中间的代码仍然很复杂。让我们考虑一下。。。似乎要将
    最大值设置为三条边中的最大值,然后将sum设置为其余边的总和。使用数组排序很容易做到这一点:

    sides = [a, b, c].sort
    
    现在,
    sides
    包含所有边的排序数组。最后一个元素将是最大的

    largest = sides.last
    
    …另外两个面可以用来求和:

    sum = sides[0] + sides[1]
    
    现在让我们看看我们现在的处境:

    def valid_triangle?(a, b, c)
      return false unless a != 0 || b != 0 || c != 0
    
      sides = [a, b, c].sort
    
      largest = sides.last
      sum = sides[0] + sides[2]
    
      return sum > largest
    end
    
    很好

    我该怎么做 对Ruby的一些内置方法有了更好的理解,这就更简单了。我不会详细介绍所有细节,但以下是我可能会如何编写此代码:

    def valid_triangle?(a, b, c)
      sides = [a, b, c].sort
      sides.all?{|s| s != 0} && sides.pop <= sides.reduce(:+)
    end
    
    接下来,我们检查所有边是否都非零

    sides.all?{|s| s != 0}
    
    然后,我们检查最大的边至少和其他边的总和一样小。我通过从排序列表中删除最大的边,然后检查该值是否小于列表中剩余两个边的总和(使用
    边找到)。减少(:+)
    ):

    sides.pop <= sides.reduce(:+)
    

    sides.pop“将代码紧跟在else之后可能是有效的语法,但看起来非常混乱。”编写适合该语言的代码非常重要。代码必须得到维护,这通常是其他人的工作,因此编写符合社区标准的代码非常重要。处理不一致的代码将导致大量的哭泣和咬牙切齿。需要改进的两件事是:
    如果a==0 | | b==0 | | c==0,则返回false
    ![a,b,c]。任何?{s | s==0}
    sum>最大的
    都是作为结尾的返回值所需要的,因为它已经返回了一个布尔值。@Brennan:这个返回值捕捉得很好,不过我想强调一下
    “false”
    false
    最初的混合用法<代码>包含?
    对于第一种情况似乎更清晰。
    其他最大值=b
    其他总和+=c
    。将语句放在
    else
    后面的行中。尾随语句不是惯用语句,尤其是在第一种情况下,
    else
    块中有多行。@theTinMan:这已经被tadman指出了,所以我不想重复它。不重复它是不好的逻辑。在答案中,除了提供一个可用的答案外,我们还想教大家如何正确地编写代码。重复一个不好的做法并不是在做一件好事
    sides = [a, b, c].sort
    
    sides.all?{|s| s != 0}
    
    sides.pop <= sides.reduce(:+)