计算序数不起作用?真的很困惑



有人可以帮助我吗,因为我无法弄清楚为什么以下数字不起作用。

票价: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 == 1else。对于除1以外的所有数字,它将落入else大小写并返回'th'。对于1,它将落入第一种情况,并返回'st',并且由于它已返回第 3 行,因此它永远不会到达对不存在的elseif方法的调用,因此永远不会有NoMethodError

从中可以学到一些教训:

阅读警告:
  1. 您的代码会生成两个警告:">警告:未到达语句",用于带有elseif的两行。这应该告诉你,这些方面有问题。
  2. 注意语法突出显示:即使是 Stack Overflow 问题框中极其糟糕、技术含量低的基本语法突出显示也已经显示了您的错误。一个合适的编辑器或IDE会更加明显。
  3. 注意你的IDE:在我的IDE中,我在elseif下面得到一条黄色的波浪线,警告我方法elseif不存在。同样,它还警告我第一个return后的代码无法访问。
  4. 使用棉绒/静态代码检查器:例如,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每个分支的值,我们只需returnif的值:

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,其中使用===方法将分支的不同条件值与顶部的测试值进行比较(对于Integers来说,这只是相等的,因此在这种情况下它将做正确的事情):

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));
}

最新更新