Преобразовать логический результат в число / целое число


276

У меня есть переменная, которая хранит falseили true, но мне нужно 0или 1вместо, соответственно. Как я могу это сделать?


8
Вот сравнение производительности некоторых из предоставленных методов: jsperf.com/conversion-from-boolean-to-number .
Сэм

4
Пользователи Node.JS захотят использовать bool === true ? 1 : 0, так как он на сегодняшний день самый быстрый в V8.
Qix - МОНИКА БЫЛА ПОВРЕЖДЕНА

3
или простоbool ? 1 : 0;
Atrahasis

Ответы:


343

Javascript имеет троичный оператор, который вы можете использовать:

var i = result ? 1 : 0;

7
Лучший ответ. Зачем? Это работает на правдивости, которая является более общей и принимает любой тип (строка, число и т. Д.). Унарный ответ действительно умный, но если я передам ему строку, он вернет NaN. Так что, если вы хотите L33T и гарантируете ввод, переходите на другую, иначе лучше использовать троичный + правдивый тест.
gdibble

466

Используйте унарный +оператор , который преобразует свой операнд в число.

+ true; // 1
+ false; // 0

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


50
Хоть и круто (я никогда не думал об этом), оно невероятно медленное (если быть точным, на 97% медленнее в Chrome). Будьте осторожны!
Qix - МОНИКА БЫЛА ПОВРЕЖДЕНА

5
Проверьте эту ревизию . Number()еще медленнее.
Qix - МОНИКА БЫЛА ПОВРЕЖДЕНА

23
Похоже, bool === true ? 1 : 0это самый быстрый, с близкой секундой от bool | 0.
Qix - МОНИКА БЫЛА ПОВРЕЖДЕНА

1
Умножение (например, 3 * false) кажется неправильным, но это работает. :) Спасибо!
mattsoave

1
@DerkJanSpeelman Тот факт, что что-то не разрешено в Typescript, не означает, что вы не должны делать это в Javascript. Это разные (хотя и связанные) языки.
одинокий день

119

Imho лучшее решение:

fooBar | 0

Это используется в asm.js для принудительного использования целочисленного типа.


Один из самых быстрых; +1.
Qix - МОНИКА БЫЛА ПОВРЕЖДЕНА

3
Хороший. Также вы можете использовать «Boolean ^ 0». ИЛИ или XOR работает.
F8ER

Это не вернет 1целое число, если fooBar нет?
ESR

58

Я предпочитаю использовать функцию Number . Он берет объект и преобразует его в число.

Пример:

var myFalseBool = false;
var myTrueBool = true;

var myFalseInt = Number(myFalseBool);
console.log(myFalseInt === 0);

var myTrueInt = Number(myTrueBool);
console.log(myTrueInt === 1);

Вы можете проверить это в jsFiddle .


3
Это лучший ответ на сегодняшний день. Внизу конечно. Только «он берет объект» не правильно.
Руди

2
Ссылка на MDN гораздо лучше , чем w3schools (EEEK!): Developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
Olivvv

Я думаю, что это лучший способ, потому что он легко читается и раскрывает намерения.
Сэм

3
Это также самый медленный.
Qix - МОНИКА БЫЛА НЕЗАБЫВАЕМАЯ

45

Я создал сравнение JSperf всех предложенных ответов.

TL; DR - лучший вариант для всех существующих браузеров:

val | 0;

,

Обновить:

Кажется, что в наши дни все они довольно идентичны, за исключением того, что Number()функция самая медленная, а самая лучшая val === true ? 1 : 0;.


2
Интересно, что троичный теперь самый быстрый в Chrome 64.0.3282 на macOS 10.13.3.
2540625

Это был бы самый быстрый вариант, в то время. Это отличается от того, чтобы быть лучшим вариантом.
mikemaccana


30

Я только что наткнулся на этот ярлык сегодня.

~~ (истина)

~~ (ложь)

Люди намного умнее, чем я могу объяснить

http://james.padolsey.com/javascript/double-bitwise-not/


2
Интересный. Я узнал что-то новое сегодня. Я не буду использовать эту технику в любом проекте, потому что она может сбить меня с толку или партнеров по команде.
nicholaides

1
hacky js - моя любимая серьезно, +1
Тодд

16

Когда JavaScript ожидает числовое значение, но получает вместо него логическое значение, он преобразует это логическое значение в число: true и false преобразуются в 1 и 0 соответственно. Таким образом, вы можете воспользоваться этим;

var t = true;
var f = false;

console.log(t*1); // t*1 === 1
console.log(f*1); // f*1 === 0 

console.log(+t); // 0+t === 1 or shortened to +t === 1
console.log(+f); //0+f === 0 or shortened to +f === 0

Дальнейшее чтение Преобразования типов Глава 3.8 Полное руководство по Javascript.


13

Унарный +оператор позаботится об этом:

var test = true;
// +test === 1
test = false;
// +test === 0

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


Я изменил комментарии на ===, потому что true == 1это правда, даже если вы "явное преобразование :-) true === 1вместо этого ложно.
xanatos

13

Я просто имел дело с этой проблемой в каком-то коде, который писал. Моим решением было использовать побитовое и.

var j = bool & 1;

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

function toInt( val ) {
    return val & 1;
}

var j = toInt(bool);

Изменить - 10 сентября 2014 г.

По какой-то причине в Chrome не выполняется преобразование с использованием троичного оператора с идентичным оператору. Не имеет смысла, почему это быстрее, но я полагаю, что это своего рода оптимизация низкого уровня, которая имеет смысл где-то по пути.

var j = boolValue === true ? 1 : 0;

Проверьте сами: http://jsperf.com/boolean-int-conversion/2

В FireFox и Internet Explorer использование версии, которую я разместил, обычно происходит быстрее.

Редактировать - 14 июля 2017

Хорошо, я не собираюсь говорить вам, какой из них вы должны или не должны использовать. Каждый взбешенный браузер постоянно поднимал и опускался в зависимости от того, насколько быстро они могут выполнять операции с каждым методом. В какой-то момент у Chrome битовая версия работала лучше, чем у других, но вдруг все стало намного хуже. Я не знаю, что они делают, поэтому я просто оставлю это тем, кого это волнует. Редко есть причина беспокоиться о том, как быстро выполняется такая операция. Даже на мобильном телефоне это пустая операция.

Кроме того, вот новый метод для добавления прототипа toInt, который нельзя перезаписать.

Object.defineProperty(Boolean.prototype, "toInt", { value: function()
{
    return this & 1;
}});

У меня было два отрицательных отзыва за этот пост. Почему бы тебе не объяснить, почему ты это проголосовал? В противном случае это просто отрицательный голос без оправдания.
Николас Р. Грант

1
В 99 раз результаты jsperf просто ведут вас по пути преждевременной оптимизации, оптимизируя наносекунды вне цикла, когда вместо этого вы должны сосредоточиться на этом уродливом операторе SQL. спасибо за предоставление нескольких разных способов подойти к этому
RozzA

Какой оператор SQL? Здесь нет ни одного запроса. Если вы имеете в виду JSPerf, я связывал это с чужим тестом. Это не мое. Честно говоря, меня это не волнует, потому что это пустая операция. Я создал свой собственный язык, который был почти функциональным, идентичным JS, и я помню, что приведение к int было глупо быстрой операцией. Восхождения по прототипу цепей не было. Вот почему я по-прежнему рекомендую первый способ сделать это с простой функцией, которая может быть встроена компилятором.
Николас Р. Грант

вещь SQL - это обобщение. спасибо за понимание
RozzA

9

Вы также можете добавить 0, использовать операторы shift или xor:

val + 0;
val ^ 0;
val >> 0;
val >>> 0;
val << 0;

Они имеют те же скорости, что и ответы других.


7

В моем контексте, React Native, где я получаю значение непрозрачности из логического, самый простой способ: использовать унарный оператор +.

+ true; // 1
+ false; // 0

Это преобразует логическое число в число;

style={ opacity: +!isFirstStep() }

4

Вы можете сделать это, просто расширив логический прототип

Boolean.prototype.intval = function(){return ~~this}

Нелегко понять, что там происходит, поэтому альтернативная версия будет

Boolean.prototype.intval = function(){return (this == true)?1:0}

сделав что вы можете сделать такие вещи, как

document.write(true.intval());

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

Boolean.prototype.intval = function(places)
{
 places = ('undefined' == typeof(places))?0:places; 
 return (~~this) << places
}

с помощью которого вы можете сделать

document.write(true.intval(2))

который производит 4 в качестве своего выхода.




1

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

Работает на сервере Ubuntu 14.04, nodejs v8.12.0 - 26/10/18

    let i = 0;
console.time("TRUE test1")
    i=0;
    for(;i<100000000;i=i+1){
        true ? 1 : 0;
    }
console.timeEnd("TRUE test1")


console.time("FALSE test2")
    i=0;
    for(;i<100000000;i=i+1){
        false ? 1 : 0;
    }
console.timeEnd("FALSE test2")

console.log("----------------------------")

console.time("TRUE test1.1")
    i=0;
    for(;i<100000000;i=i+1){
        true === true ? 1 : 0;
    }
console.timeEnd("TRUE test1.1")


console.time("FALSE test2.1")
    i=0;
    for(;i<100000000;i=i+1){
        false === true ? 1 : 0;
    }
console.timeEnd("FALSE test2.1")

console.log("----------------------------")

console.time("TRUE test3")
    i=0;
    for(;i<100000000;i=i+1){
        true | 0;
    }
console.timeEnd("TRUE test3")

console.time("FALSE test4")
    i=0;
    for(;i<100000000;i=i+1){
        false | 0;
    }
console.timeEnd("FALSE test4")

console.log("----------------------------")

console.time("TRUE test5")
    i=0;
    for(;i<100000000;i=i+1){
        true * 1;
    }
console.timeEnd("TRUE test5")

console.time("FALSE test6")
    i=0;
    for(;i<100000000;i=i+1){
        false * 1;
    }
console.timeEnd("FALSE test6")

console.log("----------------------------")

console.time("TRUE test7")
    i=0;
    for(;i<100000000;i=i+1){
        true & 1;
    }
console.timeEnd("TRUE test7")

console.time("FALSE test8")
    i=0;
    for(;i<100000000;i=i+1){
        false & 1;
    }
console.timeEnd("FALSE test8")

console.log("----------------------------")

console.time("TRUE test9")
    i=0;
    for(;i<100000000;i=i+1){
        +true;
    }
console.timeEnd("TRUE test9")

console.time("FALSE test10")
    i=0;
    for(;i<100000000;i=i+1){
        +false;
    }
console.timeEnd("FALSE test10")

console.log("----------------------------")

console.time("TRUE test9.1")
    i=0;
    for(;i<100000000;i=i+1){
        0+true;
    }
console.timeEnd("TRUE test9.1")

console.time("FALSE test10.1")
    i=0;
    for(;i<100000000;i=i+1){
        0+false;
    }
console.timeEnd("FALSE test10.1")

console.log("----------------------------")

console.time("TRUE test9.2")
    i=0;
    for(;i<100000000;i=i+1){
        -true*-1;
    }
console.timeEnd("TRUE test9.2")

console.time("FALSE test10.2")
    i=0;
    for(;i<100000000;i=i+1){
        -false*-1;
    }
console.timeEnd("FALSE test10.2")

console.log("----------------------------")

console.time("TRUE test9.3")
    i=0;
    for(;i<100000000;i=i+1){
        true-0;
    }
console.timeEnd("TRUE test9.3")

console.time("FALSE test10.3")
    i=0;
    for(;i<100000000;i=i+1){
        false-0;
    }
console.timeEnd("FALSE test10.3")

console.log("----------------------------")

console.time("TRUE test11")
    i=0;
    for(;i<100000000;i=i+1){
        Number(true);
    }
console.timeEnd("TRUE test11")

console.time("FALSE test12")
    i=0;
    for(;i<100000000;i=i+1){
        Number(false);
    }
console.timeEnd("FALSE test12")

console.log("----------------------------")

console.time("TRUE test13")
    i=0;
    for(;i<100000000;i=i+1){
        true + 0;
    }
console.timeEnd("TRUE test13")

console.time("FALSE test14")
    i=0;
    for(;i<100000000;i=i+1){
        false + 0;
    }
console.timeEnd("FALSE test14")

console.log("----------------------------")

console.time("TRUE test15")
    i=0;
    for(;i<100000000;i=i+1){
        true ^ 0;
    }
console.timeEnd("TRUE test15")

console.time("FALSE test16")
    i=0;
    for(;i<100000000;i=i+1){
        false ^ 0;
    }
console.timeEnd("FALSE test16")

console.log("----------------------------")

console.time("TRUE test17")
    i=0;
    for(;i<100000000;i=i+1){
        true ^ 0;
    }
console.timeEnd("TRUE test17")

console.time("FALSE test18")
    i=0;
    for(;i<100000000;i=i+1){
        false ^ 0;
    }
console.timeEnd("FALSE test18")

console.log("----------------------------")

console.time("TRUE test19")
    i=0;
    for(;i<100000000;i=i+1){
        true >> 0;
    }
console.timeEnd("TRUE test19")

console.time("FALSE test20")
    i=0;
    for(;i<100000000;i=i+1){
        false >> 0;
    }
console.timeEnd("FALSE test20")

console.log("----------------------------")

console.time("TRUE test21")
    i=0;
    for(;i<100000000;i=i+1){
        true >>> 0;
    }
console.timeEnd("TRUE test21")

console.time("FALSE test22")
    i=0;
    for(;i<100000000;i=i+1){
        false >>> 0;
    }
console.timeEnd("FALSE test22")

console.log("----------------------------")

console.time("TRUE test23")
    i=0;
    for(;i<100000000;i=i+1){
        true << 0;
    }
console.timeEnd("TRUE test23")

console.time("FALSE test24")
    i=0;
    for(;i<100000000;i=i+1){
        false << 0;
    }
console.timeEnd("FALSE test24")

console.log("----------------------------")

console.time("TRUE test25")
    i=0;
    for(;i<100000000;i=i+1){
        ~~true;
    }
console.timeEnd("TRUE test25")

console.time("FALSE test26")
    i=0;
    for(;i<100000000;i=i+1){
        ~~false;
    }
console.timeEnd("FALSE test26")

console.log("----------------------------")

console.time("TRUE test25.1")
    i=0;
    for(;i<100000000;i=i+1){
        ~true*-1-1;
    }
console.timeEnd("TRUE test25.1")

console.time("FALSE test26.1")
    i=0;
    for(;i<100000000;i=i+1){
        ~false*-1-1;
    }
console.timeEnd("FALSE test26.1")

console.log("----------------------------")

console.time("TRUE test27")
    i=0;
    for(;i<100000000;i=i+1){
        true/1;
    }
console.timeEnd("TRUE test27")

console.time("FALSE test28")
    i=0;
    for(;i<100000000;i=i+1){
        false/1;
    }
console.timeEnd("FALSE test28")

результат

TRUE test1: 93.301ms
FALSE test2: 102.854ms
----------------------------
TRUE test1.1: 118.979ms
FALSE test2.1: 119.061ms
----------------------------
TRUE test3: 97.265ms
FALSE test4: 108.389ms
----------------------------
TRUE test5: 85.854ms
FALSE test6: 87.449ms
----------------------------
TRUE test7: 83.126ms
FALSE test8: 84.992ms
----------------------------
TRUE test9: 99.683ms
FALSE test10: 87.080ms
----------------------------
TRUE test9.1: 85.587ms
FALSE test10.1: 86.050ms
----------------------------
TRUE test9.2: 85.883ms
FALSE test10.2: 89.066ms
----------------------------
TRUE test9.3: 86.722ms
FALSE test10.3: 85.187ms
----------------------------
TRUE test11: 86.245ms
FALSE test12: 85.808ms
----------------------------
TRUE test13: 84.192ms
FALSE test14: 84.173ms
----------------------------
TRUE test15: 81.575ms
FALSE test16: 81.699ms
----------------------------
TRUE test17: 81.979ms
FALSE test18: 81.599ms
----------------------------
TRUE test19: 81.578ms
FALSE test20: 81.452ms
----------------------------
TRUE test21: 115.886ms
FALSE test22: 88.935ms
----------------------------
TRUE test23: 82.077ms
FALSE test24: 81.822ms
----------------------------
TRUE test25: 81.904ms
FALSE test26: 82.371ms
----------------------------
TRUE test25.1: 82.319ms
FALSE test26.1: 96.648ms
----------------------------
TRUE test27: 89.943ms
FALSE test28: 83.646ms

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.