답변:
루비에는이 기능이 내장되어 있습니다 :
Integer('1001') # => 1001
Integer('1001 nights')
# ArgumentError: invalid value for Integer: "1001 nights"
Joseph Pecoraro의 답변에서 언급했듯이 0x
16 진수 및 0b
2 진수로 시작하는 것과 같이 10 진수가 아닌 유효한 문자열 과 0으로 시작하는 더 까다로운 숫자를 8 진수로 구문 분석 할 수 있습니다.
Ruby 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+$/)
\z
을 고려하십시오 \Z
. "문자열 끝과 일치합니다. 문자열이 줄 바꿈으로 끝나는 경우 줄 바꿈 직전에 일치합니다" -ruby-doc.org/core-2.1.1/Regexp .html
또한 현재 승인 된 솔루션이 16 진, 8 진 및 2 진 숫자 구문 분석에 미칠 수있는 영향에 유의하십시오.
>> Integer('0x15')
# => 21
>> Integer('0b10')
# => 2
>> Integer('077')
# => 63
루비에서 시작 0x
하거나 0X
16 진수 0b
이거나 0B
2 0
진수이며 8 진수입니다. 이것이 원하는 동작이 아닌 경우 문자열을 패턴과 먼저 일치하는지 확인하는 다른 솔루션과 결합 할 수 있습니다. 등 /\d+/
등 정규 표현식,
Myron의 답변이 마음에 들지만 "더 이상 Java / C #을 사용하지 않으므로 상속을 다시는 사용하지 않습니다"라는 Ruby 질병으로 고통 받고 있습니다 . 클래스를 열면 위험에 처할 수 있으며 특히 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
그런 다음 숫자가 될 수있는 문자열을 사용하려면 수행중인 작업이 명확하고 핵심 클래스를 방해하지 않습니다.
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.
이진 숫자 확인 등과 같이 초기화에 다른 모든 검사를 추가 할 수 있습니다. 그러나 가장 중요한 것은 Ruby는 사람들을위한 것이며 사람들을위한 것은 명확성을 의미한다는 것 입니다. 변수 이름 과 클래스 이름을 통해 객체의 이름을 지정하면 훨씬 명확 해집니다.
마지막 프로젝트 에서이 문제를 해결해야했으며 구현은 비슷하지만 약간 다릅니다.
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
재 : 크리스의 대답
당신의 구현은 "1a"또는 "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
\z
을 고려하십시오 \Z
. "문자열 끝과 일치합니다. 문자열이 줄 바꿈으로 끝나는 경우 줄 바꿈 직전에 일치합니다" -ruby-doc.org/core-2.1.1/Regexp .html
^
과$
는 다르게 메타 문자 와 미묘한 의미 가 있습니다. 당신은 아마 사용에 의미\A
와\Z
대신.