tag section script samp bootstrap 3school ruby string string-parsing

ruby - section - wbr tag in html5



AnĂ¡lisis entero seguro en Ruby (8)

Tengo una cadena, digamos ''123'' , y quiero convertirla a 123 .

Sé que puedes simplemente hacer some_string.to_i , pero eso convierte a ''lolipops'' en 0 , que no es el efecto que tengo en mente. Quiero que explote en mi cara cuando trato de convertir algo inválido, con una agradable y dolorosa Exception . De lo contrario, no puedo distinguir entre un 0 válido y algo que simplemente no es un número en absoluto.

EDITAR: Estaba buscando la forma estándar de hacerlo, sin engaños regex.


Esto podría funcionar:

i.to_i if i.match(/^/d+$/)


Me gusta la respuesta de Myron, pero sufre de la enfermedad de Ruby de "Ya no uso Java / C #, así que nunca volveré a utilizar la herencia" . Abrir cualquier clase puede ser peligroso y debe usarse con moderación, especialmente cuando es parte de la biblioteca principal de Ruby. No digo que nunca lo use, pero generalmente es fácil de evitar y hay mejores opciones disponibles, por ejemplo

class IntegerInString < String def initialize( s ) fail ArgumentError, "The string ''#{s}'' is not an integer in a string, it''s just a string." unless s =~ /^/-?[0-9]+$/ super end end

Entonces, cuando desee utilizar una cadena que podría ser un número, está claro lo que está haciendo y no le molesta a ninguna clase central, por ejemplo

n = IntegerInString.new "2" n.to_i # => 2 IntegerInString.new "blob" ArgumentError: The string ''blob'' is not an integer in a string, it''s just a string.

Puede agregar todo tipo de otras comprobaciones en la inicialización, como buscar números binarios, etc. Lo principal, sin embargo, es que Ruby es para las personas y para las personas significa claridad . Nombrar un objeto a través de su nombre de variable y su nombre de clase hace las cosas mucho más claras.


Otro comportamiento inesperado con la solución aceptada (con 1.8, 1.9 está bien):

>> Integer(:foobar) => 26017 >> Integer(:yikes) => 26025

así que si no está seguro de lo que se está transmitiendo, asegúrese de agregar un .to_s .


Re: la respuesta de Chris

Su implementación permite el paso de "1a" o "b2". ¿Qué tal esto en su lugar?

def safeParse2(strToParse) if strToParse =~ //A/d+/Z/ strToParse.to_i else raise Exception end end ["100", "1a", "b2", "t"].each do |number| begin puts safeParse2(number) rescue Exception puts "#{number} is invalid" end end

Esto produce:

100 1a is invalid b2 is invalid t is invalid


Ruby tiene esta funcionalidad integrada:

Integer(''1001'') # => 1001 Integer(''1001 nights'') # ArgumentError: invalid value for Integer: "1001 nights"

Como señaló Joseph Pecoraro en su respuesta, es posible que desee buscar cadenas que sean números válidos no decimales, como los que comienzan con 0x para hexadecimal y 0b para binario, y potencialmente más complicados comenzando con cero que se analizarán como octal .

Ruby 1.9.2 añadió un segundo argumento opcional para radix, por lo que se puede evitar el problema anterior:

Integer(''23'') # => 23 Integer(''0x23'') # => 35 Integer(''023'') # => 19 Integer(''0x23'', 10) # => #<ArgumentError: invalid value for Integer: "0x23"> Integer(''023'', 10) # => 23


También tenga en cuenta los efectos que la solución aceptada actual puede tener en el análisis de números hexadecimales, octales y binarios:

>> Integer(''0x15'') # => 21 >> Integer(''0b10'') # => 2 >> Integer(''077'') # => 63

En Ruby, los números que comienzan con 0x o 0X son hexadecimales, 0b o 0B son binarios, y solo 0 son octal. Si este no es el comportamiento deseado, puede combinarlo con algunas de las otras soluciones que comprueban si la cadena coincide primero con un patrón. Como las expresiones //d+/ regulares, etc.


Tuve que lidiar con esto en mi último proyecto, y mi implementación fue similar, pero un poco diferente:

class NotAnIntError < StandardError end class String def is_int? self =~ /^-?[0-9]+$/ end def safe_to_i return self.to_i if is_int? raise NotAnIntError, "The string ''#{self}'' is not a valid integer.", caller end end class Integer def safe_to_i return self end end class StringExtensions < Test::Unit::TestCase def test_is_int assert "98234".is_int? assert "-2342".is_int? assert "02342".is_int? assert !"+342".is_int? assert !"3-42".is_int? assert !"342.234".is_int? assert !"a342".is_int? assert !"342a".is_int? end def test_safe_to_i assert 234234 == 234234.safe_to_i assert 237 == "237".safe_to_i begin "a word".safe_to_i fail ''safe_to_i did not raise the expected error.'' rescue NotAnIntError # this is what we expect.. end end end


someString = "asdfasd123" number = someString.to_i if someString != number.to_s puts "oops, this isn''t a number" end

Probablemente no sea la forma más limpia de hacerlo, pero debería funcionar.