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

时间:2017-10-22 06:49:41

标签: ruby

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

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

5 个答案:

答案 0 :(得分:3)

如果查看语法突出显示,您可以很容易地看到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. 使用linter / static code checker :例如,RuboCop也会在第一个return之后找到无法访问的代码。
  5. 修复代码的最明显方法是简单地使用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方法将分支的不同条件值与顶部的测试值进行比较只是平等,所以在这种情况下它会做正确的事情):

    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
    

答案 1 :(得分:2)

ruby​​中没有elseif个关键字。它是elsif

为了避免这种拼写错误,最好在这种情况下使用case

case right_digit
when 1 then "st"
when 2 then "nd"
when 3 then "rd"
else "th"
end

此外,无需显式return方法中的最后一个语句,它是自动完成的。

答案 2 :(得分:2)

这样的问题有助于查找表格,因为它使事情变得极其简单:

ORDINAL = %w[ th st nd rd th th th th th th ]

def ordinal(n)
  ORDINAL[n % 10 ]
end

现在你可以打电话给ordinal(999)而不必做任何特别的准备,以提取“正确的数字”。

答案 3 :(得分:1)

正如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: 

答案 4 :(得分:1)

更简洁:

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