J'ai les éléments suivants dans mon contrôleur d'application:
def is_number?(object)
true if Float(object) rescue false
end
et la condition suivante dans mon contrôleur:
if mystring.is_number?
end
La condition génère une undefined method
erreur. Je suppose que j'ai défini is_number
au mauvais endroit ...?
ruby-on-rails
ruby
string
integer
Jamie Buchanan
la source
la source
Réponses:
Créer une
is_number?
méthode.Créez une méthode d'assistance:
Et puis appelez-le comme ceci:
Prolongez la
String
classe.Si vous voulez pouvoir appeler
is_number?
directement la chaîne au lieu de la passer en tant que paramètre à votre fonction d'assistance, vous devez la définiris_number?
comme une extension de laString
classe, comme ceci:Et puis vous pouvez l'appeler avec:
la source
to_f
dans ce qui précède, et Float () ne présente pas ce comportement:Float("330.346.11")
relancesArgumentError: invalid value for Float(): "330.346.11"
lib/core_ext/string.rb
.is_number?(string)
bit fonctionne avec Ruby 1.9. Peut-être que cela fait partie de Rails ou 1.8?String.is_a?(Numeric)
travaux. Voir aussi stackoverflow.com/questions/2095493/… .Voici une référence pour les moyens courants de résoudre ce problème. Notez que celui que vous devriez utiliser dépend probablement du ratio de faux cas attendus.
Si la performance n'a pas d'importance, utilisez ce que vous aimez. :-)
Détails de vérification des nombres entiers:
Détails de la vérification du flotteur:
la source
la source
/^\d+$/
n'est pas une expression régulière sûre dans Ruby,/\A\d+\Z/
est. (par exemple, "42 \ nsome text" reviendraittrue
)/^\d+$/
s'il s'agit de lignes, mais dans ce cas, il s'agit du début et de la fin d'une chaîne/\A\d+\Z/
.S'appuyer sur l'exception levée n'est pas la solution la plus rapide, lisible ou fiable.
Je ferais ce qui suit:
la source
expect(my_string).to match(/^[0-9]+$/)
my_string =~ /\A-?(\d+)?\.?\d+\Z/
il vous permet de faire ".1", "-0.1" ou "12" mais pas "" ou "-" ou "."Depuis Ruby 2.6.0, les méthodes de
exception
conversion numériques ont un argument optionnel [1] . Cela nous permet d'utiliser les méthodes intégrées sans utiliser d'exceptions comme flux de contrôle:Par conséquent, vous n'avez pas à définir votre propre méthode, mais vous pouvez vérifier directement des variables comme par exemple
la source
c'est comme ça que je le fais, mais je pense aussi qu'il doit y avoir un meilleur moyen
la source
object = "1.2e+35"; object.to_f.to_s == object
et ça a marchénon, vous l'utilisez mal. votre numéro_is? a un argument. tu l'as appelé sans l'argument
tu devrais faire is_number? (mystring)
la source
mystring
est effectivement une chaîne,mystring.is_a?(Integer)
sera toujours faux. On dirait qu'il veut un résultat commeis_number?("12.4") #=> true
Tl; dr: Utilisez une approche regex. Il est 39 fois plus rapide que l'approche de sauvetage dans la réponse acceptée et gère également des cas tels que "1 000"
-
La réponse acceptée par @Jakob S fonctionne pour la plupart, mais attraper des exceptions peut être très lent. De plus, l'approche de sauvetage échoue sur une chaîne comme "1,000".
Définissons les méthodes:
Et maintenant quelques cas de test:
Et un peu de code pour exécuter les cas de test:
Voici la sortie des cas de test:
Il est temps de faire quelques benchmarks de performance:
Et les résultats:
la source
5.4e-29
. Je suppose que votre expression régulière pourrait être modifiée pour les accepter également.Dans les rails 4, vous devez mettre
require File.expand_path('../../lib', __FILE__) + '/ext/string'
dans votre config / application.rbla source
Si vous préférez ne pas utiliser d'exceptions dans le cadre de la logique, vous pouvez essayer ceci:
Ou, si vous voulez qu'il fonctionne sur toutes les classes d'objets, remplacez-le
class String
parclass Object
un self converti en chaîne:!!(self.to_s =~ /^-?\d+(\.\d*)?$/)
la source
nil?
zéro est vrai sur rubis, vous pouvez donc le faire juste!!(self =~ /^-?\d+(\.\d*)?$/)
!!
fonctionne certainement. Au moins un guide de style Ruby ( github.com/bbatsov/ruby-style-guide ) a suggéré d'éviter!!
en faveur de la.nil?
lisibilité, mais j'ai vu!!
utilisé dans des référentiels populaires, et je pense que c'est un bon moyen de convertir en booléen. J'ai édité la réponse.utilisez la fonction suivante:
alors,
is_numeric? "1.2f"
= fauxis_numeric? "1.2"
= vraiis_numeric? "12f"
= fauxis_numeric? "12"
= vraila source
"0"
. Notez également que la méthode.try
ne fait pas partie de la bibliothèque principale de Ruby et n'est disponible que si vous incluez ActiveSupport."12"
, donc votre quatrième exemple dans cette question est faux."12.10"
et"12.00"
échouer aussi.À quel point cette solution est-elle stupide?
la source