题
我有一串说 '123'
, 我想转换到它 123
.
我知道你可以简单地做 some_string.to_i
, 但这转换 'lolipops'
要 0
, ,它不是影响我的想法。我想它来吹在我的脸时,我试着把东西无效的,有一个很好的和痛苦的 Exception
.否则,我不能之间的区别有效的 0
有什么东西,只是不是数量。
编辑: 我一直在寻找的标准的方式这样做,而不regex欺骗。
解决方案
红宝石具有这一功能建立在:
Integer('1001') # => 1001
Integer('1001 nights')
# ArgumentError: invalid value for Integer: "1001 nights"
如答案 约瑟夫*Pecoraro, 你可能想看串是有效的非十进制数字,例如那些开始 0x
为hex和 0b
为二,并且可能更加棘手的人数从零开始,将进行分析作为八.
红宝石1.9.2加入任择第二个参数为基数,使上述问题可以避免:
Integer('23') # => 23
Integer('0x23') # => 35
Integer('023') # => 19
Integer('0x23', 10)
# => #<ArgumentError: invalid value for Integer: "0x23">
Integer('023', 10) # => 23
其他提示
这个可能的工作:
i.to_i if i.match(/^\d+$/)
还应注意的影响,目前接受的解决方案可能会对分析六、八和二进制数字:
>> Integer('0x15')
# => 21
>> Integer('0b10')
# => 2
>> Integer('077')
# => 63
在红宝石数字开始 0x
或 0X
是六角, 0b
或 0B
是二进制的,只是 0
是八.如果不是所期望的行为您可能想要结合起来,与一些其他的解决方案,检查,如果串匹配模式的第一个。喜欢的 /\d+/
经常表达,等等。
另一个意想不到的行为所接受的解决方案(与1.8,1.9是确定):
>> Integer(:foobar)
=> 26017
>> Integer(:yikes)
=> 26025
所以如果你不知道什么是正在通过在,请确保您添加一个 .to_s
.
我喜欢麦隆的答案,但它遭受疾病的红宝石 "我不再使用Java/C#所以我永远不会使用继承一次".打开任何类可以充满危险并且应当谨慎使用, 尤其是 当它的一部分,红宝石的核心图书馆。我没说永远不要使用它,但是它通常是很容易避免,而且有更好的可供选择,例如
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
然后当你希望使用的字符串可能是一个数量很明显你在做什么和你没破坏任何核心类,例如
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.
你可以添加其他各种检查,在初始化,如检查用的二进制数字等等。最主要的是,红宝石,是对人民和正在对人们意味着 清楚的.命名的一个目通过它的变量名称 和 其类名称使得事情 很多 更加清晰。
我不得不处理与这在我的最后一个项目,以及我的执行情况是相似的,但是有点不同:
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
someString = "asdfasd123"
number = someString.to_i
if someString != number.to_s
puts "oops, this isn't a number"
end
可能不干净的方式做到这一点,但是应该的工作。
再: 克里斯的回答
你执行我们的东西,如"1"或"b2"通过。这个怎么样:
def safeParse2(strToParse)
if strToParse =~ /\A\d+\Z/
strToParse.to_i
else
raise Exception
end
end
["100", "1a", "b2", "t"].each do |number|
begin
puts safeParse2(number)
rescue Exception
puts "#{number} is invalid"
end
end
这种产出:
100
1a is invalid
b2 is invalid
t is invalid