복붙노트

[RUBY-ON-RAILS] 테스트 문자열은 루비 온 레일즈의 숫자 인 경우

RUBY-ON-RAILS

테스트 문자열은 루비 온 레일즈의 숫자 인 경우

내 응용 프로그램 컨트롤러에 다음이있다 :

def is_number?(object)
  true if Float(object) rescue false
end

내 컨트롤러에 다음과 같은 조건 :

if mystring.is_number?

end

조건은 미정있어서 오류를 던지고. 내가 잘못된 위치에 is_number 정의한 같은데요 ...?

해결법

  1. ==============================

    1.도우미 메서드를 만듭니다

    도우미 메서드를 만듭니다

    def is_number? string
      true if Float(string) rescue false
    end
    

    그리고 다음과 같이 호출 :

    my_string = '12.34'
    
    is_number?( my_string )
    # => true
    

    당신은 is_number 전화를 할 수있게하려면? 대신 직접 도우미 함수에 PARAM로 전달하는 문자열에, 당신은 is_number 정의 할 필요가? 그래서 같은 String 클래스의 확장으로 :

    class String
      def is_number?
        true if Float(self) rescue false
      end
    end
    

    그리고 당신은 그것을로 호출 할 수 있습니다 :

    my_string.is_number?
    # => true
    
  2. ==============================

    2.다음은이 문제를 해결하기위한 일반적인 방법에 대한 벤치 마크입니다. 당신은 아마 사용해야 하나의 참고가 예상 거짓 케이스의 비율에 따라 달라집니다.

    다음은이 문제를 해결하기위한 일반적인 방법에 대한 벤치 마크입니다. 당신은 아마 사용해야 하나의 참고가 예상 거짓 케이스의 비율에 따라 달라집니다.

    성능은 문제가 당신이 좋아하는 무엇을 사용하지 않는 경우. :-)

    # 1.9.3-p448
    #
    # Calculating -------------------------------------
    #                 cast     57485 i/100ms
    #            cast fail      5549 i/100ms
    #                 to_s     47509 i/100ms
    #            to_s fail     50573 i/100ms
    #               regexp     45187 i/100ms
    #          regexp fail     42566 i/100ms
    # -------------------------------------------------
    #                 cast  2353703.4 (±4.9%) i/s -   11726940 in   4.998270s
    #            cast fail    65590.2 (±4.6%) i/s -     327391 in   5.003511s
    #                 to_s  1420892.0 (±6.8%) i/s -    7078841 in   5.011462s
    #            to_s fail  1717948.8 (±6.0%) i/s -    8546837 in   4.998672s
    #               regexp  1525729.9 (±7.0%) i/s -    7591416 in   5.007105s
    #          regexp fail  1154461.1 (±5.5%) i/s -    5788976 in   5.035311s
    
    require 'benchmark/ips'
    
    int = '220000'
    bad_int = '22.to.2'
    
    Benchmark.ips do |x|
      x.report('cast') do
        Integer(int) rescue false
      end
    
      x.report('cast fail') do
        Integer(bad_int) rescue false
      end
    
      x.report('to_s') do
        int.to_i.to_s == int
      end
    
      x.report('to_s fail') do
        bad_int.to_i.to_s == bad_int
      end
    
      x.report('regexp') do
        int =~ /^\d+$/
      end
    
      x.report('regexp fail') do
        bad_int =~ /^\d+$/
      end
    end
    
    # 1.9.3-p448
    #
    # Calculating -------------------------------------
    #                 cast     47430 i/100ms
    #            cast fail      5023 i/100ms
    #                 to_s     27435 i/100ms
    #            to_s fail     29609 i/100ms
    #               regexp     37620 i/100ms
    #          regexp fail     32557 i/100ms
    # -------------------------------------------------
    #                 cast  2283762.5 (±6.8%) i/s -   11383200 in   5.012934s
    #            cast fail    63108.8 (±6.7%) i/s -     316449 in   5.038518s
    #                 to_s   593069.3 (±8.8%) i/s -    2962980 in   5.042459s
    #            to_s fail   857217.1 (±10.0%) i/s -    4263696 in   5.033024s
    #               regexp  1383194.8 (±6.7%) i/s -    6884460 in   5.008275s
    #          regexp fail   723390.2 (±5.8%) i/s -    3613827 in   5.016494s
    
    require 'benchmark/ips'
    
    float = '12.2312'
    bad_float = '22.to.2'
    
    Benchmark.ips do |x|
      x.report('cast') do
        Float(float) rescue false
      end
    
      x.report('cast fail') do
        Float(bad_float) rescue false
      end
    
      x.report('to_s') do
        float.to_f.to_s == float
      end
    
      x.report('to_s fail') do
        bad_float.to_f.to_s == bad_float
      end
    
      x.report('regexp') do
        float =~ /^[-+]?[0-9]*\.?[0-9]+$/
      end
    
      x.report('regexp fail') do
        bad_float =~ /^[-+]?[0-9]*\.?[0-9]+$/
      end
    end
    
  3. ==============================

    3.

    class String
      def numeric?
        return true if self =~ /\A\d+\Z/
        true if Float(self) rescue false
      end
    end  
    
    p "1".numeric?  # => true
    p "1.2".numeric? # => true
    p "5.4e-29".numeric? # => true
    p "12e20".numeric? # true
    p "1a".numeric? # => false
    p "1.2.3.4".numeric? # => false
    
  4. ==============================

    4.제기 예외에 의존하는 것은 가장 빠른, 읽을 수없고 신뢰할 수있는 솔루션이 아닙니다. 나는 다음을 수행 할 것입니다 :

    제기 예외에 의존하는 것은 가장 빠른, 읽을 수없고 신뢰할 수있는 솔루션이 아닙니다. 나는 다음을 수행 할 것입니다 :

    my_string.should =~ /^[0-9]+$/
    
  5. ==============================

    5.이것은 내가 그것을 할 방법입니다,하지만 난 더 나은 방법이있을 너무 생각

    이것은 내가 그것을 할 방법입니다,하지만 난 더 나은 방법이있을 너무 생각

    object.to_i.to_s == object || object.to_f.to_s == object
    
  6. ==============================

    6.어떤 당신은 잘못을 사용하고 있습니다. 당신의 is_number? 인수가 있습니다. 당신은 인수없이 호출

    어떤 당신은 잘못을 사용하고 있습니다. 당신의 is_number? 인수가 있습니다. 당신은 인수없이 호출

    당신은 is_number 일을해야 하는가? (mystring에)

  7. ==============================

    7.TL; DR : 사용 정규식 접근 방식. 더 빠른 허용 대답의 구조 방식에 비해 39x이며, 또한 "1000"와 같은 경우를 처리

    TL; DR : 사용 정규식 접근 방식. 더 빠른 허용 대답의 구조 방식에 비해 39x이며, 또한 "1000"와 같은 경우를 처리

    def regex_is_number? string
      no_commas =  string.gsub(',', '')
      matches = no_commas.match(/-?\d+(?:\.\d+)?/)
      if !matches.nil? && matches.size == 1 && matches[0] == no_commas
        true
      else
        false
      end
    end
    

    --

    @Jakob S에 의해 허용 대답은 대부분 작동하지만, 예외를 잡기 정말 속도가 느려질 수 있습니다. 또한, 구조 방식은 "1000"와 같은 문자열에 실패합니다.

    하자는 방법을 정의 :

    def rescue_is_number? string
      true if Float(string) rescue false
    end
    
    def regex_is_number? string
      no_commas =  string.gsub(',', '')
      matches = no_commas.match(/-?\d+(?:\.\d+)?/)
      if !matches.nil? && matches.size == 1 && matches[0] == no_commas
        true
      else
        false
      end
    end
    

    그리고 지금 어떤 테스트 케이스 :

    test_cases = {
      true => ["5.5", "23", "-123", "1,234,123"],
      false => ["hello", "99designs", "(123)456-7890"]
    }
    

    그리고 약간의 코드는 테스트 케이스를 실행합니다 :

    test_cases.each do |expected_answer, cases|
      cases.each do |test_case|
        if rescue_is_number?(test_case) != expected_answer
          puts "**rescue_is_number? got #{test_case} wrong**"
        else
          puts "rescue_is_number? got #{test_case} right"
        end
    
        if regex_is_number?(test_case) != expected_answer
          puts "**regex_is_number? got #{test_case} wrong**"
        else
          puts "regex_is_number? got #{test_case} right"
        end  
      end
    end
    

    여기에 테스트 케이스의 출력은 다음과 같습니다

    rescue_is_number? got 5.5 right
    regex_is_number? got 5.5 right
    rescue_is_number? got 23 right
    regex_is_number? got 23 right
    rescue_is_number? got -123 right
    regex_is_number? got -123 right
    **rescue_is_number? got 1,234,123 wrong**
    regex_is_number? got 1,234,123 right
    rescue_is_number? got hello right
    regex_is_number? got hello right
    rescue_is_number? got 99designs right
    regex_is_number? got 99designs right
    rescue_is_number? got (123)456-7890 right
    regex_is_number? got (123)456-7890 right
    

    시간은 약간의 성능 벤치 마크를 할 수 :

    Benchmark.ips do |x|
    
      x.report("rescue") { test_cases.values.flatten.each { |c| rescue_is_number? c } }
      x.report("regex") { test_cases.values.flatten.each { |c| regex_is_number? c } }
    
      x.compare!
    end
    

    그리고 결과 :

    Calculating -------------------------------------
                  rescue   128.000  i/100ms
                   regex     4.649k i/100ms
    -------------------------------------------------
                  rescue      1.348k (±16.8%) i/s -      6.656k
                   regex     52.113k (± 7.8%) i/s -    260.344k
    
    Comparison:
                   regex:    52113.3 i/s
                  rescue:     1347.5 i/s - 38.67x slower
    
  8. ==============================

    8.레일 4에서는 둘 필요가 File.expand_path ( '../../ LIB', __FILE__)가 필요 + '/ 내선 / 문자열' 당신의 설정 / application.rb에서

    레일 4에서는 둘 필요가 File.expand_path ( '../../ LIB', __FILE__)가 필요 + '/ 내선 / 문자열' 당신의 설정 / application.rb에서

  9. ==============================

    9.루비 2.6.0로, 숫자 캐스트 방법은 선택적 예외 인자 [1]이있다. 이 사용하는 우리를있게 내장 된 제어 흐름과 같은 예외를 사용하지 않고 방법 :

    루비 2.6.0로, 숫자 캐스트 방법은 선택적 예외 인자 [1]이있다. 이 사용하는 우리를있게 내장 된 제어 흐름과 같은 예외를 사용하지 않고 방법 :

    Float('x') # => ArgumentError (invalid value for Float(): "x")
    Float('x', exception: false) # => nil
    

    따라서, 당신은 당신의 자신의 방법을 정의 할 필요는 없지만, 직접 예를 들어, 같은 변수를 확인하실 수 있습니다

    if Float(my_var, exception: false)
      # do something if my_var is a float
    end
    
  10. ==============================

    10.당신은 논리의 일부로 사용 예외하지 않으려면, 당신은이를 시도 할 수 있습니다 :

    당신은 논리의 일부로 사용 예외하지 않으려면, 당신은이를 시도 할 수 있습니다 :

    class String
       def numeric?
        !!(self =~ /^-?\d+(\.\d*)?$/)
      end
    end
    

    또는, 당신이 모든 개체 클래스에서 작동 문자열로 클래스 객체에 변환 자체를 클래스 문자열을 교체하려면 : !! (self.to_s = ~ /^-?\d+(\.\d*)?$/ )

  11. ==============================

    11.다음 함수를 사용합니다 :

    다음 함수를 사용합니다 :

    def is_numeric? val
        return val.try(:to_f).try(:to_s) == val
    end
    

    그래서,

    각각 is_numeric? "1.2f"= 거짓

    각각 is_numeric? "1.2"= 참

    각각 is_numeric? "12F"= 거짓

    각각 is_numeric? "12"진정한 =

  12. ==============================

    12.이 솔루션은 어떻게 바보입니까?

    이 솔루션은 어떻게 바보입니까?

    def is_number?(i)
      begin
        i+0 == i
      rescue TypeError
        false
      end
    end
    
  13. from https://stackoverflow.com/questions/5661466/test-if-string-is-a-number-in-ruby-on-rails by cc-by-sa and MIT license