How to test if a string is basically an integer in quotes using Ruby

Ruby

Ruby Problem Overview


I need a function, is_an_integer, where

  • "12".is_an_integer? returns true.
  • "blah".is_an_integer? returns false.

How can I do this in Ruby? I would write a regex but I'm assuming there is a helper for this that I am not aware of.

Ruby Solutions


Solution 1 - Ruby

Well, here's the easy way:

class String
  def is_integer?
    self.to_i.to_s == self
  end
end

>> "12".is_integer?
=> true
>> "blah".is_integer?
=> false

I don't agree with the solutions that provoke an exception to convert the string - exceptions are not control flow, and you might as well do it the right way. That said, my solution above doesn't deal with non-base-10 integers. So here's the way to do with without resorting to exceptions:

  class String
    def integer? 
      [                          # In descending order of likeliness:
        /^[-+]?[1-9]([0-9]*)?$/, # decimal
        /^0[0-7]+$/,             # octal
        /^0x[0-9A-Fa-f]+$/,      # hexadecimal
        /^0b[01]+$/              # binary
      ].each do |match_pattern|
        return true if self =~ match_pattern
      end
      return false
    end
  end

Solution 2 - Ruby

You can use regular expressions. Here is the function with @janm's suggestions.

class String
	def is_i?
	   !!(self =~ /\A[-+]?[0-9]+\z/)
	end
end

An edited version according to comment from @wich:

class String
	def is_i?
	   /\A[-+]?\d+\z/ === self
	end
end

In case you only need to check positive numbers

  if !/\A\d+\z/.match(string_to_check)
      #Is not a positive number
  else
      #Is all good ..continue
  end  

Solution 3 - Ruby

You can use Integer(str) and see if it raises:

def is_num?(str)
  !!Integer(str)
rescue ArgumentError, TypeError
  false
end

It should be pointed out that while this does return true for "01", it does not for "09", simply because 09 would not be a valid integer literal. If that's not the behaviour you want, you can add 10 as a second argument to Integer, so the number is always interpreted as base 10.

Solution 4 - Ruby

Ruby 2.6.0 enables casting to an integer without raising an exception, and will return nil if the cast fails. And since nil mostly behaves like false in Ruby, you can easily check for an integer like so:

if Integer(my_var, exception: false)
  # do something if my_var can be cast to an integer
end

Solution 5 - Ruby

"12".match(/^(\d)+$/)      # true
"1.2".match(/^(\d)+$/)     # false
"dfs2".match(/^(\d)+$/)    # false
"13422".match(/^(\d)+$/)   # true

Solution 6 - Ruby

You can do a one liner:

str = ...
int = Integer(str) rescue nil

if int
  int.times {|i| p i}
end

or even

int = Integer(str) rescue false

Depending on what you are trying to do you can also directly use a begin end block with rescue clause:

begin
  str = ...
  i = Integer(str)

  i.times do |j|
    puts j
  end
rescue ArgumentError
  puts "Not an int, doing something else"
end

Solution 7 - Ruby

class String
  def integer?
    Integer(self)
    return true
  rescue ArgumentError
    return false
  end
end
  1. It isn't prefixed with is_. I find that silly on questionmark methods, I like "04".integer? a lot better than "foo".is_integer?.
  2. It uses the sensible solution by sepp2k, which passes for "01" and such.
  3. Object oriented, yay.

Solution 8 - Ruby

The Best and Simple way is using Float

val = Float "234" rescue nil

Float "234" rescue nil #=> 234.0

Float "abc" rescue nil #=> nil

Float "234abc" rescue nil #=> nil

Float nil rescue nil #=> nil

Float "" rescue nil #=> nil

Integer is also good but it will return 0 for Integer nil

Solution 9 - Ruby

I prefer:

config/initializers/string.rb

class String
  def number?
    Integer(self).is_a?(Integer)
  rescue ArgumentError, TypeError
    false
  end
end

and then:

[218] pry(main)> "123123123".number?
=> true
[220] pry(main)> "123 123 123".gsub(/ /, '').number?
=> true
[222] pry(main)> "123 123 123".number?
=> false

or check phone number:

"+34 123 456 789 2".gsub(/ /, '').number?

Solution 10 - Ruby

A much simpler way could be

/(\D+)/.match('1221').nil? #=> true
/(\D+)/.match('1a221').nil? #=> false
/(\D+)/.match('01221').nil? #=> true

Solution 11 - Ruby

Personally I like the exception approach although I would make it a little more terse:

class String
  def integer?(str)
    !!Integer(str) rescue false
  end
end

However, as others have already stated, this doesn't work with Octal strings.

Solution 12 - Ruby

  def isint(str)
    return !!(str =~ /^[-+]?[1-9]([0-9]*)?$/)
  end

Solution 13 - Ruby

This might not be suitable for all cases simplely using:

"12".to_i   => 12
"blah".to_i => 0

might also do for some.

If it's a number and not 0 it will return a number. If it returns 0 it's either a string or 0.

Solution 14 - Ruby

Here's my solution:

# /initializers/string.rb
class String
  IntegerRegex = /^(\d)+$/

  def integer?
    !!self.match(IntegerRegex)
  end
end

# any_model_or_controller.rb
'12345'.integer? # true
'asd34'.integer? # false

And here's how it works:

  • /^(\d)+$/is regex expression for finding digits in any string. You can test your regex expressions and results at http://rubular.com/.
  • We save it in a constant IntegerRegex to avoid unnecessary memory allocation everytime we use it in the method.
  • integer? is an interrogative method which should return true or false.
  • match is a method on string which matches the occurrences as per the given regex expression in argument and return the matched values or nil.
  • !! converts the result of match method into equivalent boolean.
  • And declaring the method in existing String class is monkey patching, which doesn't change anything in existing String functionalities, but just adds another method named integer? on any String object.

Solution 15 - Ruby

Ruby 2.4 has Regexp#match?: (with a ?)

def integer?(str)
  /\A[+-]?\d+\z/.match? str
end

For older Ruby versions, there's Regexp#===. And although direct use of the case equality operator should generally be avoided, it looks very clean here:

def integer?(str)
  /\A[+-]?\d+\z/ === str
end

integer? "123"    # true
integer? "-123"   # true
integer? "+123"   # true

integer? "a123"   # false
integer? "123b"   # false
integer? "1\n2"   # false

Solution 16 - Ruby

Expanding on @rado's answer above one could also use a ternary statement to force the return of true or false booleans without the use of double bangs. Granted, the double logical negation version is more terse, but probably harder to read for newcomers (like me).

class String
  def is_i?
     self =~ /\A[-+]?[0-9]+\z/ ? true : false
  end
end

Solution 17 - Ruby

For more generalised cases (including numbers with decimal point), you can try the following method:

def number?(obj)
  obj = obj.to_s unless obj.is_a? String
  /\A[+-]?\d+(\.[\d]+)?\z/.match(obj)
end

You can test this method in an irb session:

(irb)
>> number?(7)
=> #<MatchData "7" 1:nil>
>> !!number?(7)
=> true
>> number?(-Math::PI)
=> #<MatchData "-3.141592653589793" 1:".141592653589793">
>> !!number?(-Math::PI)
=> true
>> number?('hello world')
=> nil
>> !!number?('hello world')
=> false

For a detailed explanation of the regex involved here, check out this blog article :)

Solution 18 - Ruby

One liner in string.rb

def is_integer?; true if Integer(self) rescue false end

Solution 19 - Ruby

I'm not sure if this was around when this question is asked but for anyone that stumbles across this post, the simplest way is:

var = "12"
var.is_a?(Integer) # returns false
var.is_a?(String) # returns true

var = 12
var.is_a?(Integer) # returns true
var.is_a?(String) # returns false

.is_a? will work with any object.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTonyView Question on Stackoverflow
Solution 1 - RubySarah MeiView Answer on Stackoverflow
Solution 2 - RubyRadoView Answer on Stackoverflow
Solution 3 - Rubysepp2kView Answer on Stackoverflow
Solution 4 - RubyTimitryView Answer on Stackoverflow
Solution 5 - RubyMaciej KrasowskiView Answer on Stackoverflow
Solution 6 - RubyRobert KlemmeView Answer on Stackoverflow
Solution 7 - RubyAugust LilleaasView Answer on Stackoverflow
Solution 8 - RubySivaView Answer on Stackoverflow
Solution 9 - RubyskozzView Answer on Stackoverflow
Solution 10 - Rubygouravtiwari21View Answer on Stackoverflow
Solution 11 - RubyeightbitraptorView Answer on Stackoverflow
Solution 12 - RubyAmal Kumar SView Answer on Stackoverflow
Solution 13 - RubythreeView Answer on Stackoverflow
Solution 14 - RubySachinView Answer on Stackoverflow
Solution 15 - RubyStefanView Answer on Stackoverflow
Solution 16 - RubyadeluccarView Answer on Stackoverflow
Solution 17 - Rubytg_soView Answer on Stackoverflow
Solution 18 - Rubycb24View Answer on Stackoverflow
Solution 19 - RubyNewbieView Answer on Stackoverflow