2010-11-12 19 views
7

poco me encontré con un pedazo de código muy parecido a éste:Convertir una cadena completa en un entero en JavaScript

var nHours = parseInt(txtHours); 
if(isNaN(nHours)) // Do something 
else // Do something else with the value 

El desarrollador que escribió el código estaba bajo la impresión de que nHours sería o un entero que coincidía exactamente con txtHours o NaN. Hay varias cosas mal con esta suposición.

En primer lugar, el desarrollador de la izquierda del argumento radix que significa la entrada de "09" daría como resultado un valor de 0 en lugar de 9. Este problema se puede resolver mediante la adición de la raíz de este modo:

var nHours = parseInt(txtHours,10); 
if(isNaN(nHours)) // Do something 
else // Do something else with the value 

A continuación, la entrada de "1.5" dará lugar a un valor de 1 en lugar de NaN que no es lo que el desarrollador de esperar ya 1.5 no es un entero. Del mismo modo, un valor de "1a" dará como resultado un valor de 1 en lugar de NaN.

Todos estos problemas son algo comprensibles ya que este es uno de los ejemplos más comunes de cómo convertir una cadena a un número entero y la mayoría de los lugares no discuten estos casos.

En cualquier caso, me hizo pensar que no conozco ningún modo integrado para obtener un número entero como este. Hay Number(txtHours) (o +txtHours) que se acerca pero acepta números no enteros y tratará null y "" como 0 en lugar de NaN.

Para ayudar a los desarrolladores a cabo proporcioné la siguiente función:

function ConvertToInteger(text) 
{ 
    var number = Math.floor(+text); 
    return text && number == text ? number : NaN; 
} 

Esto parece cubrir todas las cuestiones antes mencionadas. ¿Alguien sabe de algo malo con esta técnica o tal vez una forma más simple de obtener los mismos resultados?

+0

Posiblemente duplicado [http://stackoverflow.com/questions/131406/what-is-the-best-method-to-convert-to-an-integer-in-javascript](http://stackoverflow.com/questions/131406/what-is-the-best-method-to-convert-to-an-integer-in-javascript) – subosito

+0

'Number (txtHours)' en vez de 'number (txtHours)' –

+1

Además, existe una convención de que los nombres de las funciones de los constructores están en mayúscula y los nombres de las funciones regulares no. Recomiendo seguir esa convención usando un nombre en minúsculas como 'convertToInteger' o' toInteger'. Aparte de eso, la función parece bastante sólida para mí. –

Respuesta

3

Aquí, eso es lo que ocurrió:

function integer(x) { 
    if (typeof x !== "number" && typeof x !== "string" || x === "") { 
     return NaN; 
    } else { 
     x = Number(x); 
     return x === Math.floor(x) ? x : NaN; 
    } 
} 

(Nota: he actualizado esta función para Saveguard contra las cadenas de espacios en blanco Véase más abajo..)

La idea es aceptar únicamente argumentos qué tipo es Número o Cadena (pero no el valor de cadena vacía). Luego se realiza una conversión a Número (en caso de que fuera una cadena), y finalmente su valor se compara con el valor de piso() para determinar si el número es un número entero o no.

integer(); // NaN 
integer(""); // NaN 
integer(null); // NaN 
integer(true); // NaN 
integer(false); // NaN 
integer("1a"); // NaN 
integer("1.3"); // NaN 
integer(1.3); // NaN  
integer(7); // 7 

Sin embargo, el valor NaN está "mal uso" aquí, ya que los flotadores y cadenas que representan los flotadores dan como resultado NaN, y que no es técnicamente cierto.

Además, tenga en cuenta que debido a la forma como las cadenas se convierten en números, el argumento de cadena puede haber detrás o bien dirigiéndose por espacios en blanco, o ceros a la izquierda:

integer(" 3 "); // 3  
integer("0003"); // 3 

Otro enfoque ...

Puede usar una expresión regular si el valor de entrada es una cadena. Esta expresión regular: /^\s*(\+|-)?\d+\s*$/ coincidirá con cadenas que representan enteros.

¡FUNCIÓN ACTUALIZADA!

function integer(x) { 
    if (typeof x === "string" && /^\s*(\+|-)?\d+\s*$/.test(x)) { 
     x = Number(x); 
    } 
    if (typeof x === "number") { 
     return x === Math.floor(x) ? x : NaN; 
    } 
    return NaN; 
} 

Esta versión de número entero() es más estricta ya que permite sólo cadenas que siguen un patrón determinado (que se probó con una expresión regular). Produce los mismos resultados que la otra función entero(), excepto que también descarta todas las cadenas de espacios en blanco (como lo señala @CMS).

¡Actualizado nuevamente!

me di cuenta de @ respuesta de Zecc y simplificar el código un poco ... supongo que esto funciona, también:

function integer(x) { 
    if(/^\s*(\+|-)?\d+\s*$/.test(String(x))){ 
     return parseInt(x, 10); 
    } 
    return Number.NaN; 
} 

Se probaly no es la solución más rápida (en términos de rendimiento), pero Me gusta su simplicidad :)

+0

@CMS ¡Oh, qué lío :) Un cheque de expresiones regulares podría resolver este problema. –

+0

Soy consciente de que el uso de NaN es un uso incorrecto, pero me pareció una buena manera de representar un no entero. Después de todo, no hay NaI. Hay varias cosas que podría haber hecho, incluyendo el uso de nulo, indefinido, un objeto o múltiples funciones, pero NaN era lo que el código original estaba buscando y parecía lo suficientemente claro como para seguir adelante con él. – drs9222

+0

Mi primer pensamiento cuando vi esto fue utilizar una expresión regular, pero me pareció excesivo para algo que pensé que debería ser muy simple. Si quisiéramos, podríamos evitarlo recortando la entrada si se trata de una cadena. – drs9222

-1

Primero puede convertir una Cadena en un Entero, y luego volver a una Cadena de nuevo. Luego verifique si las cadenas primera y segunda coinciden.

Editar: un ejemplo de lo que quería decir:

function cs (stringInt) { 
    var trimmed = stringInt.trim();  // trim original string 
    var num = parseInt(trimmed, 10); // convert string to integer 
    newString = num + "";    // convert newly created integer back to string 
    console.log(newString);    // (works in at least Firefox and Chrome) check what's new string like 
    return (newString == trimmed);  // if they are identical, you can be sure that original string is an integer 
} 

Esta función devolverá verdadero si una cadena se pone en realidad es un entero. Se puede modificar si no quieres recortar. El uso de ceros a la izquierda fallará, pero, una vez más, puede deshacerse de ellos en esta función si lo desea. De esta manera, no necesita perder el tiempo con NaN o regex, puede verificar fácilmente la validez de su entero codificado.

+0

@darioo Convierte una cadena en un entero ... ¿cómo? Hay varios métodos. –

+0

@ Šime Vidas: He actualizado mi respuesta. Diría que aún es la mejor manera de convertir una cadena en un número entero. – darioo

+0

Sospecho que lo hizo por diseño, pero su ejemplo fallará si se utiliza como entrada algo que no sea una cadena, incluido un entero. Tampoco devuelve el número entero real para su uso. – drs9222

1

Aquí está mi intento:

function integer(x) { 
    var n = parseFloat(x); // No need to check typeof x; parseFloat does it for us 
    if(!isNaN(n) && /^\s*(\+|-)?\d+\s*$/.test(String(x))){ 
     return n; 
    } 
    return Number.NaN; 
} 

tengo que acreditar Šime Vidas para la expresión regular, aunque me gustaría llegar a mí mismo.

Editar: No sabía que había un NaN global. Siempre he usado Number.NaN.
Vive y aprende.

+1

En realidad, usar Number.NaN en lugar de NaN es una buena elección, ya que la variable global NaN se puede sobrescribir con cualquier otro valor (var NaN = "foo") y la propiedad Number.NaN no. –

1

Mi solución implica algún truco barato. Se basa en el hecho de que los operadores de bits en Javascript convierten sus operandos en enteros.

No estaba muy seguro de si las cadenas que representan enteros deberían funcionar, por lo que aquí hay dos soluciones diferentes.

function integer (number) { 
    return ~~number == number ? ~~number : NaN; 
} 

function integer (number) { 
    return ~~number === number ? ~~number : NaN; 
} 

El primero funcionará con ambos enteros como cadenas, el segundo no. El operador bit (~) no de bits convertirá su operando en un número entero. Este método falla para enteros más grandes que no pueden ser representados por la representación de 32 bits de números enteros (-2147483647 .. 2147483647).

Cuestiones relacionadas