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(:+)