Tenho o seguinte em meu controlador de aplicativo:
def is_number?(object)
true if Float(object) rescue false
end
e a seguinte condição no meu controlador:
if mystring.is_number?
end
A condição está gerando um undefined method
erro. Estou supondo que defini is_number
no lugar errado ...?
ruby-on-rails
ruby
string
integer
Jamie Buchanan
fonte
fonte
Respostas:
is_number?
Método de criação .Crie um método auxiliar:
E então chame assim:
Estender
String
aula.Se você deseja chamar
is_number?
diretamente a string em vez de passá-la como um parâmetro para sua função auxiliar, você precisa definiris_number?
como uma extensão daString
classe, assim:E então você pode chamá-lo com:
fonte
to_f
acima, e Float () não exibe esse comportamento:Float("330.346.11")
aumentosArgumentError: invalid value for Float(): "330.346.11"
lib/core_ext/string.rb
.is_number?(string)
funcione no Ruby 1.9. Talvez seja parte do Rails ou 1.8?String.is_a?(Numeric)
trabalho. Consulte também stackoverflow.com/questions/2095493/… .Aqui está uma referência para maneiras comuns de resolver esse problema. Observe qual você deve usar provavelmente depende da proporção de casos falsos esperada.
Se o desempenho não importa, use o que quiser. :-)
Detalhes de verificação de inteiros:
Detalhes de verificação do flutuador:
fonte
fonte
/^\d+$/
não é uma regexp segura em Ruby,/\A\d+\Z/
é. (por exemplo, "42 \ nalgo texto" retornariatrue
)/^\d+$/
se estiver lidando com linhas, mas neste caso é sobre o início e o fim de uma string/\A\d+\Z/
.Contar com a exceção levantada não é a solução mais rápida, legível ou confiável.
Eu faria o seguinte:
fonte
expect(my_string).to match(/^[0-9]+$/)
my_string =~ /\A-?(\d+)?\.?\d+\Z/
permite que você faça '.1', '-0,1' ou '12', mas não '' ou '-' ou '.'A partir do Ruby 2.6.0, os métodos de cast numérico têm um
exception
argumento opcional [1] . Isso nos permite usar os métodos integrados sem usar exceções como fluxo de controle:Portanto, você não precisa definir seu próprio método, mas pode verificar diretamente variáveis como, por exemplo,
fonte
é assim que eu faço, mas também acho que deve haver uma maneira melhor
fonte
object = "1.2e+35"; object.to_f.to_s == object
e funcionounão, você está apenas usando errado. seu is_number? tem um argumento. você chamou sem o argumento
você deveria estar fazendo is_number? (mystring)
fonte
mystring
for realmente uma String,mystring.is_a?(Integer)
sempre será falso. Parece que ele quer um resultado comois_number?("12.4") #=> true
Tl; dr: use uma abordagem regex. É 39 vezes mais rápido do que a abordagem de resgate na resposta aceita e também lida com casos como "1.000"
-
A resposta aceita por @Jakob S funciona na maior parte, mas detectar exceções pode ser muito lento. Além disso, a abordagem de resgate falha em uma string como "1.000".
Vamos definir os métodos:
E agora alguns casos de teste:
E um pequeno código para executar os casos de teste:
Aqui está o resultado dos casos de teste:
É hora de fazer alguns benchmarks de desempenho:
E os resultados:
fonte
5.4e-29
. Eu acho que sua regex pode ser ajustada para aceitá-los também.No rails 4, você precisa colocar
require File.expand_path('../../lib', __FILE__) + '/ext/string'
em seu config / application.rbfonte
Se preferir não usar exceções como parte da lógica, você pode tentar o seguinte:
Ou, se você quiser que funcione em todas as classes de objeto, substitua
class String
porclass Object
um convert self em uma string:!!(self.to_s =~ /^-?\d+(\.\d*)?$/)
fonte
nil?
zero é confiável no ruby, então você pode fazer apenas!!(self =~ /^-?\d+(\.\d*)?$/)
!!
certamente funciona. Pelo menos um guia de estilo Ruby ( github.com/bbatsov/ruby-style-guide ) sugeriu evitar!!
em favor da.nil?
legibilidade, mas já vi!!
usado em repositórios populares e acho que é uma boa maneira de converter para booleano. Eu editei a resposta.use a seguinte função:
tão,
is_numeric? "1.2f"
= falsois_numeric? "1.2"
= verdadeirois_numeric? "12f"
= falsois_numeric? "12"
= verdadeirofonte
"0"
. Observe também que o método.try
não faz parte da biblioteca central do Ruby e só está disponível se você incluir o ActiveSupport."12"
, então seu quarto exemplo nesta questão está errado."12.10"
e"12.00"
falhar também.Quão idiota é essa solução?
fonte