Test if a string is basically an integer in quotes

2019-01-01 11:09发布

问题:

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 im assuming there is a helper for this that i am not aware of

回答1:

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  


回答2:

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

EDIT: 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


回答3:

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

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

Addendum: 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.

Addendum to addendum: Fixed this by changing Integer(str) to Integer(str, 10), as per @jason-axelson\'s comment.



回答4:

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


回答5:

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


回答6:

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.


回答7:

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



回答8:

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?


回答9:

personally I like the exception approach although I would make it a little terser.

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

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



回答10:

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


回答11:

A much simpler way could be

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


回答12:

Might not be suitable for all cases but a simple

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

might also do for some.

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



回答13:

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

Explanation:

  • /^(\\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.


回答14:

Although explicit use of the case equality operator should be avoided, Regexp#=== 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


回答15:

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 :)



回答16:

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


回答17:

One liner in string.rb

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


回答18:

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!



回答19:

you can use is_a? method. for eg. 1.is_a? Integer will return true



标签: ruby