Hello people,
how to check string to know if it is number or not.
ex: isnumber('text') ==> false isnumber('22') ==> true
Thanks.
Hello people,
how to check string to know if it is number or not.
ex: isnumber('text') ==> false isnumber('22') ==> true
Thanks.
There are a few ways to do this. I'll give some examples for checking if the string is an integer, which might be sufficient for you. Checking for floats, rationals, etc will be more complex.
# is_integer.rb class String def is_integer? !self.empty? && self =~ /\A\d+\Z/ # not the empty string and containing only one or more digits end
def is_integer2? !self.empty? && Integer(self) rescue false # not the empty string and capable of being coerced by Integer() end
def is_integer3? !self.empty? && self.scan(/\D/).empty? # not the empty string and containing no non-digit characters end end
Here is one benchmark:
["", "1", "123", "foo", "foo123"].each { |string| string.is_integer?} # (n = 10,000) user system total real regex: 0.070000 0.000000 0.070000 ( 0.065365) Integer(): 0.580000 0.040000 0.620000 ( 0.620194) scan: 0.150000 0.000000 0.150000 ( 0.150243)
Using Integer and rescuing the thrown exception is quick for integer strings but grossly inefficient for non-integer strings (as expected). The regex is fastest all-around of the three examples given and benchmarking shows that short-circuiting on the empty string really speeds up the special case of "".is_integer?
Feel free to suggest other implementations. I'll put the lib, unit test and benchmark files on my blog for you to use. (As soon as I get my blog up and running. Probably tomorrow. Stay tuned.) Until then, here's the benchmark used above:
# is_integer_bm.rb require 'benchmark' require 'is_integer' # your is_integer.rb where the extension to String is located
STRINGS = ["", "1", "123", "foo", "foo123"]
def bench_total n = 10000 puts "\n" print STRINGS.inspect print".each { |string| string.is_integer?}" print " # (n = 10,000)\n" Benchmark.bm(10) do |x| x.report(" regex:") { n.times { STRINGS.each{ |str| str.is_integer? } } } x.report("Integer():") { n.times { STRINGS.each{ |str| str.is_integer2? } } } x.report(" scan:") { n.times { STRINGS.each{ |str| str.is_integer3? } } } end end
bench_total
Rein
def isnumber(string) string.to_i.to_s == string ? true : false end
-faisal
faisal,
The ternary here is useless as == already returns a boolean, and this is also integer only rather than any number, so changing your method to:
class String def is_integer? self.to_i.to_s == self end end
and adding it to the benchmark, we get:
["", "1", "123", "foo", "foo123"].each { |string| string.is_integer?} # (n = 10,000) user system total real regex: 0.070000 0.000000 0.070000 ( 0.069953) Integer(): 0.580000 0.040000 0.620000 ( 0.635358) scan: 0.150000 0.000000 0.150000 ( 0.172896) to_i.to_s: 0.150000 0.000000 0.150000 ( 0.157933)
Or roughly equal to the scan method but still about half as fast as
the regex. So far you're in second place. Thanks for playing
Incidentally faisal's method does actually work as a test for integer- ness. (There has to be a better word...) My only issue with it is that it is not very intention revealing. Then again, neither is the regex if you aren't familiar with regexen.
Incidentally, the regex method without the check for empty? is actually slightly faster overall than with the check for empty? so the most performant method so far is:
class String def is_integer? self =~ /\A\d+\Z/ end end
rewritten in a object oriented manner:
class String def is_integer? self.to_i >= 1 end end
"0".is_integer? #=> false "-123".is_integer? #=> false
'fraid not.
You did, however, remind me about negative integers.
class String def is_integer? self =~ /\A-?\d+\Z/ end end
and the scan method won't work on negative integers. Whoops!
For posterity: http://reinh.com/2007/9/4/string-is_integer
Rein
i could argue that it's mostly for readability, although having used a ternary in the first place i could argue that i should have an entire chorus lined up to laugh at the code.
-faisal