8

在 ruby​​ 中,我正在解析以下格式的日期:24092008。我想将每个部分(年、月、日)转换为数字。

我使用生成三个字符串的正则表达式将它们拆分,我将它们传递给 Integer 构造函数。

  date =~ /^([\d]{2})([\d]{2})([\d]{4})/
  year = Integer($3)
  month = Integer($2)
  day = Integer($1)

当它到达月线时,它崩溃如下:

`Integer': invalid value for Integer: "09" (ArgumentError)

我花了一段时间才意识到它将前导零解释为八进制,而 09 不是有效的八进制数(它可以与“07”一起正常工作)。

有没有一个优雅的解决方案,或者我应该只测试小于 10 的数字并首先删除零?

谢谢。

4

4 回答 4

15

我不熟悉正则表达式,所以如果这个答案离题,请原谅我。我一直假设 $3、$2 和 $1 是字符串。这是我在 IRB 中复制问题的方法:

irb(main):003:0> Integer("04")
=> 4
irb(main):004:0> Integer("09")
ArgumentError: invalid value for Integer: "09"
    from (irb):4:in `Integer'
    from (irb):4
    from :0

但看起来 .to_i 没有同样的问题:

irb(main):005:0> "04".to_i
=> 4
irb(main):006:0> "09".to_i
=> 9
于 2008-09-28T20:36:02.363 回答
7

指定基数 10

明确地告诉 Ruby 你想将字符串解释为以 10 为底的数字。

Integer("09", 10) # => 9

.to_i你想要严格要好。

"123abc".to_i # => 123
Integer("123abc", 10) # => ArgumentError

我是怎么想出来的

irbmethod(:Integer)返回#<Method: Object(Kernel)#Integer>。这告诉我Kernel拥有这个方法,我在内核上查找了文档。方法签名表明它需要一个基数作为第二个参数。

于 2015-07-22T14:40:08.387 回答
1

也许(0([\d])|([1-9][\d]))代替([\d]{2}) You 可能不得不使用 $2、$4 和 $5 代替 $1、$2、$3。

或者,如果您的正则表达式支持(?:...),则使用(?:0([\d])|([1-9][\d]))

由于 ruby​​ 从 perl 中获取其正则表达式,因此后一个版本应该可以工作。

于 2008-09-28T20:52:03.370 回答
0

而不是直接检查任何带有前导 0 的整数。例如:

Integer("08016") #=> ArgumentError: invalid value for Integer(): "08016"

创建一个方法来检查和救援前导 0:

def is_numeric(data)
  _is_numeric = true if Integer(data) rescue false

  # To deal with Integers with leading 0
  if !_is_numeric
    _is_numeric = data.split("").all?{|q| Integer(q.to_i).to_s == q }
  end

  _is_numeric
end

is_numeric("08016") #=> true is_numeric("A8016") #=> false

于 2022-02-09T08:12:49.130 回答