有人可以帮助我吗,因为我无法弄清楚为什么以下数字不起作用。
票价:22、23、32、33 元
例如,在 if else 语句中,如果我输入 22 并且我执行 22%10,我会返回 2,但是当我转到序数方法时,它不会转到 2,而是返回
def ordinal(right_digit)
if right_digit == 1
return "st"
elseif right_digit == 2
return "nd"
elseif right_digit == 3
return "rd"
else
return "th"
end
end
puts "Enter a number: "
# converts string to an integer
input = gets.chomp.to_i
right_digit = input % 10
puts "That's the #{input}#{ordinal(right_digit)} "
如果您查看语法突出显示,您可以轻松看到elseif
没有突出显示为关键字。这是因为 Ruby中没有elseif
关键字。它拼写为elsif
.
如果你要求你的编辑器自动格式化你的代码(或者你复制并粘贴到Pry中,例如),你会看到Ruby如何解释你的代码:
def ordinal(right_digit)
if right_digit == 1
return "st"
elseif right_digit == 2
return "nd"
elseif right_digit == 3
return "rd"
else
return "th"
end
end
换句话说,由于 Ruby 中没有elseif
关键字,因此它只会将elseif
解释为方法调用。它与:
def ordinal(right_digit)
if right_digit == 1
return "st"
self.elseif(right_digit == 2)
return "nd"
self.elseif(right_digit == 3)
return "rd"
else
return "th"
end
end
因此,您的条件中只有两种情况:right_digit == 1
和else
。对于除1
以外的所有数字,它将落入else
大小写并返回'th'
。对于1
,它将落入第一种情况,并返回'st'
,并且由于它已返回第 3 行,因此它永远不会到达对不存在的elseif
方法的调用,因此永远不会有NoMethodError
。
从中可以学到一些教训:
阅读警告:- 您的代码会生成两个警告:">警告:未到达语句",用于带有
elseif
的两行。这应该告诉你,这些方面有问题。 - 注意语法突出显示:即使是 Stack Overflow 问题框中极其糟糕、技术含量低的基本语法突出显示也已经显示了您的错误。一个合适的编辑器或IDE会更加明显。
- 注意你的IDE:在我的IDE中,我在
elseif
下面得到一条黄色的波浪线,警告我方法elseif
不存在。同样,它还警告我第一个return
后的代码无法访问。 - 使用棉绒/静态代码检查器:例如,RuboCop 也会在第一次
return
后找到无法访问的代码。
修复代码的最明显方法是简单地使用正确的拼写elsif
:
def ordinal(right_digit)
if right_digit == 1
return "st"
elsif right_digit == 2
return "nd"
elsif right_digit == 3
return "rd"
else
return "th"
end
end
但是,我们还可以做更多的事情。在 Ruby 中,一切都是一个表达式,即所有东西的计算结果都是一个值。Ruby 中没有语句。因此,if
也是一个表达式,其计算结果为所采用的分支的值。因此,没有必要return
每个分支的值,我们只需return
if
的值:
def ordinal(right_digit)
return if right_digit == 1
"st"
elsif right_digit == 2
"nd"
elsif right_digit == 3
"rd"
else
"th"
end
end
其次,方法的返回值隐式是方法主体内计算的最后一个表达式的值。在这种情况下,最后一个(实际上也是唯一的)表达式是条件if
表达式,所以我们不需要显式返回它:
def ordinal(right_digit)
if right_digit == 1
"st"
elsif right_digit == 2
"nd"
elsif right_digit == 3
"rd"
else
"th"
end
end
接下来,Ruby 有一个多向条件表达式,称为case
表达式,它通常比多向if
更容易阅读:
def ordinal(right_digit)
case
when right_digit == 1
"st"
when right_digit == 2
"nd"
when right_digit == 3
"rd"
else
"th"
end
end
还有一种不同形式的case
,其中使用===
方法将分支的不同条件值与顶部的测试值进行比较(对于Integer
s来说,这只是相等的,因此在这种情况下它将做正确的事情):
def ordinal(right_digit)
case right_digit
when 1
"st"
when 2
"nd"
when 3
"rd"
else
"th"
end
end
最后,建议您仅在实际使用双引号提供的任何功能(即字符串内插和转义序列)时才使用双引号字符串:
def ordinal(right_digit)
case right_digit
when 1
'st'
when 2
'nd'
when 3
'rd'
else
'th'
end
end
ruby 中没有elseif
关键字。这是elsif
.
为了避免这种错别字,在这种情况下最好使用case
:
case right_digit
when 1 then "st"
when 2 then "nd"
when 3 then "rd"
else "th"
end
此外,无需显式return
方法中的最后一个语句,它是自动完成的。
像这样的问题适合查找表,因为它使事情变得完全琐碎:
ORDINAL = %w[ th st nd rd th th th th th th ]
def ordinal(n)
ORDINAL[n % 10 ]
end
现在您可以调用ordinal(999)
,而不必在准备提取"正确数字"的方式上做任何特殊的事情。
正如Jörg所说,阅读警告。为此,请使用-w
选项运行 ruby:
$ ruby -w t.rb
t.rb:5: warning: statement not reached
t.rb:7: warning: statement not reached
Enter a number:
更简洁地说:
ord = [nil,'st','nd','rd'][right_digit] || 'th'
或:
ord = ['th','st','nd','rd'][right_digit] || 'th'
。如果我们想要0th
.
作为一种方法:
ORDINALS = ['th','st','nd','rd']
def ordinal(nb)
ORDINALS[nb] || 'th'
end
JAVASCRIPT(用于代码片段)
const ORDS = ['th','st','nd','rd'];
function ordinal(nb){
return ORDS[nb] || 'th';
}
let i = 0 ;
for( ; i<8 ; ++i)
{
console.log(i + " + ordinal("+i+") = ", i + ordinal(i));
}