Tester si une chaîne est fondamentalement un entier entre guillemets à l’aide de Ruby?

J’ai besoin d’une fonction, is_an_integer, où

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

Comment puis-je faire ça en rbuy? j’écrirais une regex mais im supposant qu’il y a une aide pour cela que je ne suis pas au courant de

Vous pouvez utiliser des expressions régulières. Voici la fonction avec les suggestions de @ janm.

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

Une version éditée selon le commentaire de @wich:

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

Au cas où il suffirait de vérifier les nombres positifs

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

Eh bien, voici le moyen facile:

 class Ssortingng def is_integer? self.to_i.to_s == self end end >> "12".is_integer? => true >> "blah".is_integer? => false 

EDIT: Je ne suis pas d’accord avec les solutions qui provoquent une exception pour convertir la chaîne – les exceptions ne sont pas un stream de contrôle, et vous pourriez tout aussi bien le faire. Cela dit, ma solution ci-dessus ne traite pas des entiers non-base-10. Alors, voici comment faire sans recourir à des exceptions:

  class Ssortingng 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 

Vous pouvez utiliser Integer(str) et voir si cela soulève:

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

Addendum: Il convient de souligner que bien que cela soit vrai pour "01" , il ne le fait pas pour "09" , simplement parce que 09 ne serait pas un littéral entier valide.

Vous pouvez faire un seul paquebot:

 str = ... int = Integer(str) rescue nil if int int.times {|i| pi} end 

ou même

 int = Integer(str) rescue false 

Selon ce que vous essayez de faire, vous pouvez également utiliser directement un bloc begin end avec la clause rescue:

 begin str = ... i = Integer(str) i.times do |j| puts j end rescue ArgumentError puts "Not an int, doing something else" end 
 "12".match(/^(\d)+$/) # true "1.2".match(/^(\d)+$/) # false "dfs2".match(/^(\d)+$/) # false "13422".match(/^(\d)+$/) # true 
 class Ssortingng def integer? Integer(self) return true rescue ArgumentError return false end end 
  1. Il n’est pas préfixé par is_ . Je trouve ça idiot avec les méthodes de "04".integer? , j’aime bien "04".integer? beaucoup mieux que "foo".is_integer? .
  2. Il utilise la solution sensible de sepp2k, qui passe pour "01" et autres.
  3. Orienté object, yay.

Je préfère:

config / initializers / ssortingng.rb

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

et alors:

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

ou vérifier le numéro de téléphone:

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

Le meilleur et le plus simple utilise 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 est aussi bon mais il retournera 0 pour Integer nil

Personnellement, j’aime l’approche des exceptions, même si je voudrais en faire un peu plus.

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

Cependant, comme d’autres l’ont déjà dit, cela ne fonctionne pas avec les chaînes Octal …

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

Un moyen beaucoup plus simple pourrait être

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

Peut ne pas convenir à tous les cas mais un simple

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

pourrait aussi faire pour certains.

Donc, si c’est un nombre et non 0, il renverra un nombre. Si elle renvoie 0, c’est soit une chaîne de mots, soit 0.

Solution:

 # /initializers/ssortingng.rb class Ssortingng IntegerRegex = /^(\d)+$/ def integer? !!self.match(IntegerRegex) end end # any_model_or_controller.rb '12345'.integer? # true 'asd34'.integer? # false 

Explication:

  • /^(\d)+$/ est une expression rationnelle pour trouver des chiffres dans une chaîne. Vous pouvez tester vos expressions et résultats d’expressions rationnelles à l’ adresse http://rubular.com/ .
  • Nous le sauvegardons dans un IntegerRegex constant pour éviter une allocation de mémoire inutile chaque fois que nous l’utilisons dans la méthode.
  • integer? est une méthode interrogative qui devrait retourner true ou false .
  • match est une méthode sur chaîne qui correspond aux occurrences de l’expression regex donnée dans l’argument et renvoie les valeurs correspondantes ou nil .
  • !! convertit le résultat de la méthode de match en valeur booléenne équivalente.
  • Et déclarer la méthode dans la classe Ssortingng existante est un patch de singe, qui ne change rien aux fonctionnalités de Ssortingng existantes, mais ajoute simplement une autre méthode nommée integer? sur n’importe quel object Ssortingng.

Bien que l’utilisation explicite de l’opérateur d’égalité de casse soit à éviter, Regexp#=== semble très propre ici:

 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 

Pour les cas plus généralisés (y compris les nombres avec point décimal), vous pouvez essayer la méthode suivante:

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

Vous pouvez tester cette méthode dans une session irb:

 (irb) >> number?(7) => # >> !!number?(7) => true >> number?(-Math::PI) => # >> !!number?(-Math::PI) => true >> number?('hello world') => nil >> !!number?('hello world') => false 

Pour une explication détaillée de la regex impliquée ici, consultez cet article de blog 🙂

En élargissant la réponse de @robo, on pourrait aussi utiliser un énoncé ternaire pour forcer le retour de vrais ou de faux booléens sans utiliser de double bang. Certes, la version à double négation logique est plus concise, mais probablement plus difficile à lire pour les nouveaux venus (comme moi).

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

Un liner dans ssortingng.rb

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

Je ne suis pas sûr que ce soit là quand cette question est posée mais … Pour quiconque trébuche sur ce post, le plus simple est

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

.est un? travaillera avec n’importe quel object!

vous pouvez utiliser is_a? méthode. pour par exemple. 1.is_a? Entier renverra true