Конвертировать всю строку в целое число в JavaScript - PullRequest
7 голосов
/ 12 ноября 2010

Я недавно натолкнулся на кусок кода, очень похожий на этот:

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

Разработчик, написавший этот код, находился под впечатлением, что nHours будет либо целым числом, которое точно соответствует txtHours или NaN.Это предположение неверно.

Во-первых, разработчик оставил аргумент radix, который означает, что ввод "09" приведет к значению 0 вместо 9.Эту проблему можно решить, добавив основание следующим образом:

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

Далее, ввод "1.5" приведет к значению 1 вместо NaN, что не соответствует ожиданиям разработчикапоскольку 1.5 не является целым числом.Аналогично, значение "1a" приведет к значению 1 вместо NaN.

Все эти проблемы несколько понятны, поскольку это один из самых распространенных примеров того, как преобразовать строкук целому числу, и большинство мест не обсуждают эти случаи.

Во всяком случае, это заставило меня подумать, что я не знаю ни одного встроенного способа получить целое число, подобное этому.Существует Number(txtHours) (или +txtHours), который подходит ближе, но принимает нецелые числа и будет трактовать null и "" как 0 вместо NaN.

Чтобы помочь разработчику, япри условии следующей функции:

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

Это, кажется, охватывает все вышеупомянутые проблемы.Кто-нибудь знает что-нибудь не так с этой техникой или, возможно, более простой способ получить те же результаты?

Ответы [ 4 ]

3 голосов
/ 12 ноября 2010

Вот то, что я придумал:

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

(Примечание: я обновил эту функцию, чтобы защитить от пробелов. См. Ниже.)

Идея состоит в том, чтобыпринимать только аргументы, тип которых - Number или String (но не пустое строковое значение).Затем выполняется преобразование в Number (в случае, если это была строка), и, наконец, его значение сравнивается со значением floor (), чтобы определить, является ли число целым или нет.

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

Однако значение NaN здесь «неправильно используется», поскольку числа с плавающей точкой и строки, представляющие числа с плавающей точкой, приводят к значению NaN, что технически неверно.

Кроме того, обратите внимание, что из-заесли строки преобразуются в числа, строковый аргумент может иметь конечный или начальный пробел или начальные нули:

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

Другой подход ...

Вы можете использовать регулярное выражение, если входное значение является строкой.Это регулярное выражение: /^\s*(\+|-)?\d+\s*$/ будет соответствовать строкам, представляющим целые числа.

ОБНОВЛЕННАЯ ФУНКЦИЯ!

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;
}

Эта версия integer () является более строгой, поскольку она допускает только строки, которые следуют определенному шаблону (который проверяется с помощью регулярного выражения).Он выдает те же результаты, что и другая функция integer (), за исключением того, что он дополнительно игнорирует все строки пробелов (как указано @CMS).

Обновлено еще раз!

Я заметил ответ @ Zecc и немного упростил код ... Я думаю, это тоже работает:

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

Это, вероятно, не самое быстрое решение (с точки зрения производительности), но мне нравится его простота:)

1 голос
/ 14 ноября 2010

Мое решение включает в себя некоторые дешевые трюки. Он основан на том факте, что битовые операторы в Javascript преобразуют свои операнды в целые числа.

Я не совсем уверен, должны ли работать строки, представляющие целые числа, поэтому здесь есть два разных решения.

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

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

Первое будет работать с обоими целыми числами как строки, второе - нет. Битовый оператор not (~) преобразует свой операнд в целое число. Этот метод не работает для целых чисел большего размера, которые не могут быть представлены 32-битным представлением целых чисел (-2147483647 .. 2147483647).

1 голос
/ 13 ноября 2010

Вот моя попытка:

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;
}

Я должен отдать должное Шиме Видасу за регулярное выражение, хотя сам бы туда попал.

Редактировать : я не знал, что существует NaN глобальный. Я всегда использовал Number.NaN.
Живи и учись.

0 голосов
/ 13 ноября 2010

Вы можете сначала преобразовать строку в целое число, а затем снова вернуться в строку. Затем проверьте соответствие первой и второй строк.

Редактировать : пример того, что я имел в виду:

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
}

Эта функция вернет true, если введенная вами строка действительно является целым числом. Его можно изменить, если вы не хотите обрезки. Использование ведущих нулей не удастся, но, опять же, вы можете избавиться от них в этой функции, если хотите. Таким образом, вам не нужно возиться с NaN или регулярным выражением, вы можете легко проверить правильность вашего строкового целого числа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...