문제

문자열이 있습니다. '123', 그리고 그것을 다음으로 변환하고 싶습니다. 123.

나는 당신이 간단하게 할 수 있다는 것을 알고 있습니다 some_string.to_i, 하지만 이는 변환됩니다. 'lolipops' 에게 0, 이는 제가 염두에 둔 효과가 아닙니다.나는 유효하지 않은 것을 변환하려고 할 때 멋지고 고통스러운 말로 내 얼굴에 폭발하기를 원합니다. Exception.그렇지 않으면 유효한 것을 구별할 수 없습니다. 0 그리고 전혀 숫자가 아닌 것.

편집하다: 나는 정규식 속임수 없이 표준적인 방법을 찾고 있었습니다.

도움이 되었습니까?

해결책

Ruby에는 다음 기능이 내장되어 있습니다.

Integer('1001')                                    # => 1001  
Integer('1001 nights')  
# ArgumentError: invalid value for Integer: "1001 nights"  

답변에서 언급했듯이 조셉 페코라로, 다음과 같이 시작하는 문자열과 같이 유효한 십진수가 아닌 숫자인 문자열을 감시할 수 있습니다. 0x 16진수 및 0b 이진수 및 8진수로 구문 분석되는 0으로 시작하는 더 까다로운 숫자의 경우.

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

다른 팁

이것은 효과가 있을 수 있습니다:

i.to_i if i.match(/^\d+$/)

또한 현재 허용되는 솔루션이 16진수, 8진수 및 2진수 구문 분석에 미칠 수 있는 영향에 유의하세요.

>> Integer('0x15')
# => 21  
>> Integer('0b10')
# => 2  
>> Integer('077')
# => 63

다음으로 시작하는 Ruby 숫자 0x 또는 0X 16진수이고, 0b 또는 0B 바이너리이고 그냥 0 8진수이다.이것이 원하는 동작이 아닌 경우 문자열이 패턴과 먼저 일치하는지 확인하는 다른 솔루션과 결합할 수 있습니다.처럼 /\d+/ 정규 표현식 등

허용된 솔루션의 또 다른 예상치 못한 동작(1.8, 1.9는 괜찮습니다):

>> Integer(:foobar)
=> 26017
>> Integer(:yikes)
=> 26025

따라서 무엇이 전달되고 있는지 확실하지 않은 경우에는 .to_s.

나는 Myron의 답변을 좋아하지만 루비병을 앓고 있습니다. "나는 더 이상 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

그런 다음 숫자가 될 수 있는 문자열을 사용하려는 경우 수행 중인 작업이 명확하고 핵심 클래스를 손상시키지 않습니다.

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
someString = "asdfasd123"
number = someString.to_i
if someString != number.to_s
  puts "oops, this isn't a number"
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
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top