先頭にゼロがある可能性のある文字列から数値を解析するにはどうすればよいですか?
質問
ルビーでは、次の形式で日付を解析しています:24092008。 各セクション(年、月、日付)を数値に変換したい。
Integerコンストラクターに渡す3つの文字列を生成する正規表現を使用してそれらを分割しました。
date =~ /^([\d]{2})([\d]{2})([\d]{4})/
year = Integer($3)
month = Integer($2)
day = Integer($1)
月の行に達すると、次のようにクラッシュします。
`Integer': invalid value for Integer: "09" (ArgumentError)
先頭のゼロをOctalとして解釈し、09が有効なOctal番号ではないことを認識するまでに少し時間がかかりました(<!> quot; 07 <!> quot;で正常に動作します)。
これに対するエレガントな解決策はありますか、それとも単に10未満の数値をテストし、最初にゼロを削除する必要がありますか?
ありがとう。
解決
私は正規表現に精通していないので、この答えがオフベースの場合はご容赦ください。私は$ 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
他のヒント
ベース10を指定
文字列を基数10の数値として解釈することを明示的にRubyに伝えます。
Integer("09", 10) # => 9
これは、厳密にしたい場合は.to_i
よりも優れています。
"123abc".to_i # => 123
Integer("123abc", 10) # => ArgumentError
どうやってこれを理解したか
irb
では、method(:Integer)
は#<Method: Object(Kernel)#Integer>
を返します。 Kernel
がこのメソッドを所有していることを教えてくれたので、カーネルに関するドキュメントを調べました。 メソッドシグネチャは、 2番目の引数としてbase。
おそらく(0([\d])|([1-9][\d]))
の代わりに([\d]{2})
$ 1、$ 2、$ 3の代わりに$ 2、$ 4、および$ 5を使用する必要がある場合があります。
または正規表現が(?:...)
をサポートしている場合は、(?:0([\d])|([1-9][\d]))
Rubyはperlから正規表現を取得するため、この後者のバージョンは動作するはずです。