使用Ruby测试字符串是否基本上是引号中的整数?

Ton*_*ony 126 ruby

我需要一个函数,is_an_integer,其中

__PRE__

我怎么能在红宝石中这样做?我会写一个正则表达式,但我假设有一个帮助,我不知道

Sar*_*Mei 158

嗯,这是简单的方法:

class String
  def is_integer?
    self.to_i.to_s == self
  end
end

>> "12".is_integer?
=> true
>> "blah".is_integer?
=> false
Run Code Online (Sandbox Code Playgroud)

编辑:我不同意引发转换字符串异常的解决方案 - 异常不是控制流,你也可以采用正确的方式.也就是说,我上面的解决方案不涉及非基数为10的整数.所以这里是没有诉诸异常的方法:

  class String
    def integer? 
      [                          # In descending order of likeliness:
        /^[-+]?[1-9]([0-9]*)?$/, # decimal
        /^0[0-7]+$/,             # octal
        /^0x[0-9A-Fa-f]+$/,      # hexadecimal
        /^0b[01]+$/              # binary
      ].each do |match_pattern|
        return true if self =~ match_pattern
      end
      return false
    end
  end
Run Code Online (Sandbox Code Playgroud)

  • "01".to_i.to_s!="01" (22认同)
  • 你可以,但那将是糟糕的形式.您不使用异常作为控制流,并且任何人的代码都不应包含"rescue false"(或"rescue true").一些简单的gsub'ing将使我的解决方案适用于OP未指定的边缘情况. (4认同)
  • 我知道很多人都会使用它,这当然是美学上令人愉悦的.对我而言,虽然这表明代码需要重组.如果你期待一个例外......这不是一个例外. (4认同)
  • 难道你不能用`Integer self rescue false'替换`self.to_i.to_s == self`? (2认同)
  • 我同意不应将例外用作控制流程.我不认为要求是承认面向开发人员的数字.在非程序员的情况下,可以被视为一个错误,特别是考虑到前导零和八进制可能混淆.也与to_i不一致.您的代码不处理"-0123"情况.一旦处理完这种情况,就不需要单独的八进制正则表达式.你可以简单地使用"any?".函数中唯一的语句可能是"[/ re1 /,/ re2 /,/ re3 /] .any?{| re | self = ~re}",没有if子句或返回. (2认同)
  • 除了一个几乎无害的障碍:''-0'.is_integer ?,我都赞成这种解决方案。==假` (2认同)

Rad*_*ado 132

您可以使用正则表达式.这是@ janm建议的功能.

class String
    def is_i?
       !!(self =~ /\A[-+]?[0-9]+\z/)
    end
end
Run Code Online (Sandbox Code Playgroud)

根据@wich的评论编辑的版本:

class String
    def is_i?
       /\A[-+]?\d+\z/ === self
    end
end
Run Code Online (Sandbox Code Playgroud)

如果您只需要检查正数

  if !/\A\d+\z/.match(string_to_check)
      #Is not a positive number
  else
      #Is all good ..continue
  end  
Run Code Online (Sandbox Code Playgroud)

  • 两条评论.您可以使用`/ regexp/=== self`而不是`!!(self =〜/ regexp /)`构造.您可以使用字符类'\ d'而不是`[0-9]` (16认同)
  • 不错.在Ruby中,如果在函数的最后一个表达式中生成返回值,则通常会省略"return"关键字.这也将返回一个零的整数值,你可能想要一个布尔值,所以像!!(str =〜/ ^ [ - +]?[0-9] + $ /)这样的东西会这样做.然后你可以将它添加到String并省略参数,使用"self"而不是"str",然后你可以将名称更改为"is_i?" ... (4认同)
  • 谢谢!我完全不了解红宝石的惯例和做法.我刚刚在ruby和正则表达式上做了一个快速谷歌查看语法,更改了正则表达式以应用于手头的问题,并进行了测试.实际上它很漂亮..当我有更多的业余时间时,我可能需要更长时间看一下. (2认同)

sep*_*p2k 64

您可以使用Integer(str)并查看它是否会引发:

def is_num?(str)
  !!Integer(str)
rescue ArgumentError, TypeError
  false
end
Run Code Online (Sandbox Code Playgroud)

附录:应该指出的是,虽然这确实是真的"01",但它并不适用"09",因为它09不是一个有效的整数文字.

补遗附录:通过改变这个固定10Integer,按照@杰森- axelson的评论.

  • 老兄......为了转换一个数字而引发异常?例外不是控制流程. (37认同)
  • 它们不是,但不幸的是,这是确定Ruby中字符串"整数"的规范方法.使用`#to_i`的方法因为它的允许性而太过破碎. (28认同)
  • Sarah:你可以使用正则表达式但是为了处理Ruby在解析整数时所做的所有情况(负数,十六进制,八进制,下划线,例如1_000_000),这将是一个非常大的正则表达式并且容易出错.`Integer()`是规范的,因为使用`Integer()`你肯定知道Ruby认为整数文字的任何东西都会被接受,其他一切都会被拒绝.复制语言已经给你的东西可以说是比使用控制异常更糟糕的代码味道. (20认同)
  • 对于那些想知道原因的人来说,Integer("09")是无效的,因为"0"使它成为八进制,而9不是有效的八进制数.http://osdir.com/ml/lang.ruby.general/2002-08/msg00247.html (17认同)
  • @Rado所以重新发明轮子. (9认同)
  • Huzzah解决了一个荒谬的问题.在ruby中应该有更好的方法来做到这一点.正则表达式解决这个问题的必要性要荒谬得多.关于使用异常作为控制流的投诉是教条式的废话,这是一个解决问题的工作方法(虽然丑陋)有效!如果您有一个防弹regexp解决方案,请对抗红宝石核心! (3认同)
  • 还要注意使用`Integer(str)`会转换像`0x26`这样的字符串,所以更好的方法可能是`Integer(str,10)`.10只接受10号基数. (2认同)
  • @SarahMei:@ sepp2k没有使用异常作为控制流.如果他们做了类似`raise ArgumentError`之类的事情并且稍后从该异常中获救,那就是这种方式. (2认同)
  • @Rado 关于计算机科学中的异常控制流“反模式”——这并不普遍。这不是 Python 问题,而是考虑如何在 Python 中使用异常:(1) 错误处理,(2) 事件通知,(3) 特殊情况处理,(4) 终止操作,(5) 异常控制流(Mark Lutz,“学习 Python”,第 5 版,第 1082-3 页)。从 Lut'z 书中,还可以查看第 1145 页上的用于打破多个嵌套循环(使用异常)的习语。并阅读第 1146 页的异常如何不总是错误。Ruby 也可以做这些事情。鸭子类型语言不是那么教条。 (2认同)

小智 24

"12".match(/^(\d)+$/)      # true
"1.2".match(/^(\d)+$/)     # false
"dfs2".match(/^(\d)+$/)    # false
"13422".match(/^(\d)+$/)   # true
Run Code Online (Sandbox Code Playgroud)

  • 如果你需要一个布尔值`!!("12".匹配/ ^(\ d)+ $ /)`或"12".匹配(/ ^(\),请用`!!`或者使用`present?`来换行. d)+ $ /).present?`(后者需要Rails/activesupport) (4认同)
  • 它不返回true和false,而是返回MatchData实例和nil。 (2认同)

Rob*_*mme 23

你可以做一个班轮:

str = ...
int = Integer(str) rescue nil

if int
  int.times {|i| p i}
end
Run Code Online (Sandbox Code Playgroud)

甚至

int = Integer(str) rescue false
Run Code Online (Sandbox Code Playgroud)

根据您尝试的操作,您还可以直接使用带有rescue子句的begin end块:

begin
  str = ...
  i = Integer(str)

  i.times do |j|
    puts j
  end
rescue ArgumentError
  puts "Not an int, doing something else"
end
Run Code Online (Sandbox Code Playgroud)


Tim*_*try 12

Ruby 2.6.0允许在不引发异常的情况下强制转换为整数,并且nil如果强制转换失败将返回。并且由于nil其行为与falseRuby 相似,因此您可以轻松地检查整数,如下所示:

if Integer(my_var, exception: false)
  # do something if my_var can be cast to an integer
end
Run Code Online (Sandbox Code Playgroud)

  • 这是最干净的! (2认同)

Aug*_*aas 8

class String
  def integer?
    Integer(self)
    return true
  rescue ArgumentError
    return false
  end
end
Run Code Online (Sandbox Code Playgroud)
  1. 它没有前缀is_.我发现在问号方法上很傻,我"04".integer?比它好多了"foo".is_integer?.
  2. 它使用sepp2k的明智解决方案,传递"01"等等.
  3. 面向对象,耶.

  • `String#integer?`是每个Ruby编码器及其表兄喜欢添加到语言中的常见补丁,导致代码库具有三种不同的微妙不兼容的实现和意外的破坏.我在大型Ruby项目上学到了很多东西. (2认同)

Siv*_*iva 7

最好和最简单的方法是使用 Float

val = Float "234" rescue nil

Float "234" rescue nil #=> 234.0

Float "abc" rescue nil #=> nil

Float "234abc" rescue nil #=> nil

Float nil rescue nil #=> nil

Float "" rescue nil #=> nil
Run Code Online (Sandbox Code Playgroud)

Integer也不错,但它会返回0Integer nil


eig*_*tor 5

就我个人而言,我喜欢异常方法,尽管我会让它更简洁一些:

class String
  def integer?(str)
    !!Integer(str) rescue false
  end
end
Run Code Online (Sandbox Code Playgroud)

然而,正如其他人已经指出的那样,这不适用于八进制字符串。


gou*_*i21 5

一个更简单的方法可能是

/(\D+)/.match('1221').nil? #=> true
/(\D+)/.match('1a221').nil? #=> false
/(\D+)/.match('01221').nil? #=> true
Run Code Online (Sandbox Code Playgroud)


sko*_*ozz 5

我更喜欢:

配置/初始化/ string.rb

class String
  def number?
    Integer(self).is_a?(Integer)
  rescue ArgumentError, TypeError
    false
  end
end
Run Code Online (Sandbox Code Playgroud)

然后:

[218] pry(main)> "123123123".number?
=> true
[220] pry(main)> "123 123 123".gsub(/ /, '').number?
=> true
[222] pry(main)> "123 123 123".number?
=> false
Run Code Online (Sandbox Code Playgroud)

或查看电话号码:

"+34 123 456 789 2".gsub(/ /, '').number?
Run Code Online (Sandbox Code Playgroud)