wvd*_*hel 155 ruby string string-parsing
比方说我有一个字符串,'123'我想把它转换成123.
我知道你可以做到some_string.to_i,但是转换'lolipops'为0,这不是我想到的效果.当我尝试将一些无效的东西转换成一种美好而痛苦的东西时,我希望它能在我的脸上爆炸Exception.否则,我无法区分有效0和根本不是数字的东西.
编辑:我一直在寻找标准的做法,没有正则表达式的诡计.
Sla*_*ast 229
Ruby内置了这个功能:
Integer('1001') # => 1001
Integer('1001 nights')
# ArgumentError: invalid value for Integer: "1001 nights"
Run Code Online (Sandbox Code Playgroud)
正如Joseph Pecoraro在回答中所指出的那样,您可能希望查看有效非十进制数字的字符串,例如以0xfor hex和0bbinary 开头的字符串,以及可能更为棘手的数字,从零开始将被解析为八进制.
Ruby 1.9.2为radix添加了可选的第二个参数,因此可以避免上述问题:
Integer('23') # => 23
Integer('0x23') # => 35
Integer('023') # => 19
Integer('0x23', 10)
# => #<ArgumentError: invalid value for Integer: "0x23">
Integer('023', 10) # => 23
Run Code Online (Sandbox Code Playgroud)
Pur*_*eas 27
这可能有效:
i.to_i if i.match(/^\d+$/)
Run Code Online (Sandbox Code Playgroud)
Jos*_*aro 24
还要注意当前接受的解决方案可能对解析十六进制,八进制和二进制数的影响:
>> Integer('0x15')
# => 21
>> Integer('0b10')
# => 2
>> Integer('077')
# => 63
Run Code Online (Sandbox Code Playgroud)
在以十六进制开头0x或者0X是十六进制的Ruby数字中,0b或者0B是二进制数,只是0八进制数.如果这不是所需的行为,您可能希望将其与一些其他解决方案相结合,以检查字符串是否与模式匹配.像/\d+/正则表达式等
Jai*_*ham 15
接受的解决方案的另一个意外行为(1.8,1.9是可以的):
>> Integer(:foobar)
=> 26017
>> Integer(:yikes)
=> 26025
Run Code Online (Sandbox Code Playgroud)
因此,如果您不确定传入的是什么,请确保添加一个.to_s.
我喜欢Myron的答案,但它患有Ruby疾病"我不再使用Java/C#所以我永远不会再使用继承"了.打开任何课程都会充满危险,应该谨慎使用,特别是当它是Ruby核心库的一部分时.我不是说不要使用它,但它通常很容易避免,并且有更好的选择,例如
class IntegerInString < String
def initialize( s )
fail ArgumentError, "The string '#{s}' is not an integer in a string, it's just a string." unless s =~ /^\-?[0-9]+$/
super
end
end
Run Code Online (Sandbox Code Playgroud)
然后,当你想使用一个可能是数字的字符串时,它清楚你正在做什么,你不会破坏任何核心类,例如
n = IntegerInString.new "2"
n.to_i
# => 2
IntegerInString.new "blob"
ArgumentError: The string 'blob' is not an integer in a string, it's just a string.
Run Code Online (Sandbox Code Playgroud)
您可以在初始化中添加各种其他检查,例如检查二进制数等.但最重要的是,Ruby适用于人,而适用于人则意味着清晰.通过它的变量名称命名的对象和它的类名使事情变得多清晰.
小智 6
我在上一个项目中不得不处理这个问题,我的实现类似,但有点不同:
class NotAnIntError < StandardError
end
class String
def is_int?
self =~ /^-?[0-9]+$/
end
def safe_to_i
return self.to_i if is_int?
raise NotAnIntError, "The string '#{self}' is not a valid integer.", caller
end
end
class Integer
def safe_to_i
return self
end
end
class StringExtensions < Test::Unit::TestCase
def test_is_int
assert "98234".is_int?
assert "-2342".is_int?
assert "02342".is_int?
assert !"+342".is_int?
assert !"3-42".is_int?
assert !"342.234".is_int?
assert !"a342".is_int?
assert !"342a".is_int?
end
def test_safe_to_i
assert 234234 == 234234.safe_to_i
assert 237 == "237".safe_to_i
begin
"a word".safe_to_i
fail 'safe_to_i did not raise the expected error.'
rescue NotAnIntError
# this is what we expect..
end
end
end
Run Code Online (Sandbox Code Playgroud)