代码之家  ›  专栏  ›  技术社区  ›  Swanand

Ruby实现是\u numeric?对于字符串,需要更好的选择

  •  10
  • Swanand  · 技术社区  · 15 年前

    我想验证字符串的“数字性”(它不是活动记录模型中的属性)。我只需要它是一个有效的基10,正整数字符串。我这样做:

    class String
      def numeric?
        # Check if every character is a digit
        !!self.match(/\A[0-9]+\Z/)
      end
    end
    
    class String
      def numeric?
        # Check is there is *any* non-numeric character
        !self.match(/[^0-9]/)
      end
    end
    

    其中哪一个更合理?或者,还有其他更好的实现方法吗?

    8 回复  |  直到 12 年前
        1
  •  10
  •   Bkkbrad    15 年前

    请务必使用 \A \Z 而不是 ^ $ ,以匹配整个字符串,而不仅仅是字符串中的一行。如果要避免将字符串与结束换行符匹配,请在结尾使用'\z'。有关更多问题,请参阅 The Regex Tutorial on anchors .

    例如, /^[0-9]+$/ 成功匹配以下内容:

    foo
    1234
    bar
    

    但是 /\A[0-9]+\Z/ 没有。

        2
  •  5
  •   August Lilleaas    15 年前

    第一个看起来很正常。

    我会说出方法的名字 numeric? 但是。我不太喜欢 is_foo? 方法。它们在方法名中没有问号的语言中是有意义的。( is_foo , isFoo 但是有了问号, is 感觉多余。

        3
  •  3
  •   Gishu    15 年前

    我不是百分之百确定,但Rails似乎在使用 /\A[+-]?\d+\Z/ 整数。
    单击“显示源文件” validates_numericality_of here

        4
  •  2
  •   kenn    13 年前

    我建议换一种方式。另外,因为您要问“正”整数,所以我为正整数和非负整数分别做了两种方法。

    class String
      def numeric?
        !self.match(/[^0-9]/)
      end
    
      def positive_integer?
        self.to_i > 0
      end
    
      def nonnegative_integer?
        self.to_i > 0 or self == '0'
      end
    end
    

    基准代码如下:

    require 'benchmark'
    include Benchmark
    
    bmbm(100) do |x|
      x.report('numeric?') do
        "some invalid string".numeric?
      end
    
      x.report('positive_integer?') do
        "some invalid string".positive_integer?
      end
    
      x.report('nonnegative_integer?') do
        "some invalid string".nonnegative_integer?
      end
    end
    

    结果:

    numeric?
    0.000000   0.000000   0.000000 (  0.000045)
    positive_integer?
    0.000000   0.000000   0.000000 (  0.000012)
    nonnegative_integer?
    0.000000   0.000000   0.000000 (  0.000015)
    

    看起来像 positive_integer? nonnegative_integer? 在这个微观基准中更快。

    最后,作为旁注,您可以定义 integer? 方法类似:

    class String
      def integer?
        self.to_i.to_s == self
      end
    end
    
        5
  •  1
  •   zaius    15 年前

    对于非数字字符串,第二个将更快完成,因为它将拒绝第一个坏字符。

    另外,检查字符串to_i方法-它可能会执行您想要的操作:
    http://www.ruby-doc.org/core/classes/String.html#M000787

        6
  •  1
  •   moogs    15 年前

    我不知道这是不是很快,但我喜欢:

    class String
     def numeric?
        true if Integer(object) rescue false
     end
    end
    

    也处理负数。如果您将来想要支持float,只需使用float()。

        7
  •  0
  •   Lonecat    15 年前

    根据一个简单的基准,第二种方法更快,尽管我不是专家基准,所以这可能不是一个有效的基准: http://pastie.org/586777

    扎勒斯的逻辑是对的。它只需要检查一次非有效字符串。

        8
  •  0
  •   DavidJ    12 年前

    通知

    n = '1234'
    n.to_i.to_s == n
    => true
    
    n2 = '1.3'
    n.to_i.to_s == n2
    => false
    

    适用于正整数和负整数,但不适用于八进制/十六进制表示、浮点等。可能无法执行最佳(未经测试),但不会浪费时间进行过早的优化。