Converter resultado booleano em número / número inteiro

276

Eu tenho uma variável que armazena falseou true, mas preciso 0ou 1, em vez disso, respectivamente. Como posso fazer isso?

hd.
fonte
8
Aqui está uma comparação de desempenho de algumas das técnicas fornecidas: jsperf.com/conversion-from-boolean-to-number .
Sam
4
Os usuários do Node.JS vão querer usar bool === true ? 1 : 0, pois é de longe o mais rápido no V8.
Qix - MONICA FOI ERRADA
3
ou apenas #bool ? 1 : 0;
Atrahasis

Respostas:

343

Javascript tem um operador ternário que você pode usar:

var i = result ? 1 : 0;
Andy Rose
fonte
7
Melhor resposta. Por quê? Isso funciona com veracidade mais geral e aceita qualquer tipo (string, número, etc.). A resposta unária é realmente inteligente, mas se eu passar uma string, ela retorna NaN. Portanto, se você deseja L33T e garante a entrada, seja cauteloso, caso contrário, acho que o teste ternário + verdade é o melhor.
Gdibble
466

Use o operador unário+ , que converte seu operando em um número.

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

Observe, é claro, que você ainda deve limpar os dados no lado do servidor, porque um usuário pode enviar qualquer dado ao seu servidor, independentemente do código do lado do cliente.

lonesomeday
fonte
50
Embora legal (nunca pensei nisso), é incrivelmente lento (97% mais lento no Chrome, para ser exato). Seja cauteloso!
Qix - MONICA FOI ERRADA
5
Confira esta revisão . Number()é ainda mais lento.
Qix - MONICA FOI ERRADA
23
Parece bool === true ? 1 : 0ser o mais rápido, com um segundo próximo de bool | 0.
Qix - MONICA FOI ERRADA
1
Multiplicar (por exemplo, 3 * falso) parece tão errado, mas funciona. :) Obrigado!
mattsoave
1
@DerkJanSpeelman O fato de algo não ser permitido no Typescript não significa que você não deve fazê-lo em Javascript. São idiomas diferentes (embora relacionados).
Loneomeday
119

A melhor solução é:

fooBar | 0

Isso é usado no asm.js para forçar o tipo inteiro.

kralyk
fonte
Um dos mais rápidos; +1.
Qix - MONICA FOI ERRADA
3
Agradável. Além disso, você pode usar "Boolean ^ 0". OR ou XOR funciona.
F8ER 22/08/16
Isso não retornará um 1número inteiro, se fooBar não estiver?
ESR
58

Eu prefiro usar a função Number . Ele pega um objeto e o converte em um número.

Exemplo:

var myFalseBool = false;
var myTrueBool = true;

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

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

Você pode testá-lo em um jsFiddle .

René
fonte
3
Esta é a melhor resposta de longe. No fundo, é claro. Apenas "é preciso um objeto" não está certo.
Rudie
2
O link para o mdn é muito melhor do que o w3schools (eeek!): Developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/…
Olivvv
Eu acho que esse é o melhor caminho, porque é fácil de ler e revela as intenções.
Sam
3
Também é o mais lento.
Qix - MONICA FOI ERRADA EM
45

Eu criei uma comparação JSperf de todas as respostas sugeridas.

TL; DR - a melhor opção para todos os navegadores atuais é:

val | 0;

.

Atualizar:

Parece que hoje em dia eles são todos idênticos, exceto que a Number()função é a mais lenta e a melhor val === true ? 1 : 0;.

Gal Talmor
fonte
2
Curiosamente, o ternário agora é o mais rápido no Chrome 64.0.3282 no macOS 10.13.3.
2540625
Essa seria a opção mais rápida na época. Isso é diferente de ser a melhor opção.
mikemaccana 27/01
41

A maneira digitada de fazer isso seria:

Number(true) // 1
Number(false) // 0
Philip
fonte
2
Finalmente, uma resposta decente. Obrigado.
Erik Campobadal
30

Acabei de encontrar este atalho hoje.

~~ (verdadeiro)

~~ (falso)

Pessoas muito mais inteligentes do que eu posso explicar:

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

tonyjcamp
fonte
2
Interessante. Eu aprendi algo novo hoje. Porém, não usarei essa técnica em nenhum projeto, porque tem o potencial de confundir o futuro comigo ou com os colegas de equipe.
Nicholaides 8/12
1
js hacky é o meu favorito. sério, +1
Todd
16

Quando o JavaScript espera um valor numérico, mas recebe um booleano, ele o converte em um número: true e false convertem em 1 e 0, respectivamente. Então você pode tirar proveito disso;

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

Leitura adicional Conversões de tipo Capítulo 3.8 do Guia definitivo para Javascript.

Charlie Lynch
fonte
13

O +operador unário cuidará disso:

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

Naturalmente, você deseja verificar isso com integridade no servidor antes de armazená-lo, para que, de qualquer maneira, seja um local mais sensato para fazer isso.

Gustav Barkefors
fonte
Eu mudei os comentários para ===, porque true == 1é verdade mesmo sem a "conversão explícita :-), em true === 1vez disso, é falsa.
Xanatos 19/10/11
13

Eu estava lidando com esse problema em algum código que estava escrevendo. Minha solução foi usar um bit a bit e.

var j = bool & 1;

Uma maneira mais rápida de lidar com um problema constante seria criar uma função. É mais legível por outras pessoas, melhor para a compreensão no estágio de manutenção e se livra do potencial de escrever algo errado.

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

var j = toInt(bool);

Editar - 10 de setembro de 2014

Nenhuma conversão usando um operador ternário com o mesmo operador é mais rápida no Chrome por algum motivo. Não faz sentido o porquê de ser mais rápido, mas suponho que seja algum tipo de otimização de baixo nível que faça algum sentido ao longo do caminho.

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

Teste você mesmo: http://jsperf.com/boolean-int-conversion/2

No FireFox e no Internet Explorer, o uso da versão que eu publiquei geralmente é mais rápido.

Editar - 14 de julho de 2017

Ok, não vou dizer qual você deve ou não usar. Todos os navegadores estão subindo e descendo com a rapidez com que podem executar a operação com cada método. O Chrome, em um ponto, na verdade, tinha a versão bit a bit e melhor do que as outras, mas, de repente, ficou muito pior. Não sei o que eles estão fazendo, então vou deixar para quem se importa. Raramente existe motivo para se preocupar com a rapidez com que uma operação como essa é feita. Mesmo no celular, é uma operação do nada.

Além disso, eis um método mais novo para adicionar um protótipo 'toInt' que não pode ser substituído.

Object.defineProperty(Boolean.prototype, "toInt", { value: function()
{
    return this & 1;
}});
Nicholas R. Grant
fonte
Eu tive dois votos negativos para este post. Por que você não explica por que votou contra? Caso contrário, é apenas um voto negativo sem justificativa.
Nicholas R. Grant
1
99 vezes os resultados do jsperf apenas o levam ao caminho prematuro da otimização, otimizando nanossegundos de um loop quando você deve se concentrar nessa instrução SQL feia. Obrigado por fornecer algumas maneiras diferentes de abordar esta questão
ROZZA
Qual instrução SQL? Não há uma única consulta aqui. Se você está se referindo ao JSPerf, eu estava vinculando isso do teste de outra pessoa. Não é meu. Sinceramente, não me importo com o aspecto de desempenho disso, pois é uma operação do nada. Criei minha própria linguagem que era quase uma funcionalidade idêntica à JS e lembro que a conversão para int era uma operação estupidamente rápida. Escalar cadeias de protótipos não era. É por isso que eu ainda recomendaria a primeira maneira de fazê-lo, com uma função simples que pode ser incorporada pelo compilador.
Nicholas R. Grant
a coisa do SQL é uma generalização. obrigado pela visão
ROZZA
9

Você também pode adicionar 0, usar operadores shift ou xor:

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

Eles têm velocidades semelhantes às das outras respostas.

REMqb
fonte
6

No meu contexto, React Native, onde estou obtendo o valor de opacidade do booleano, a maneira mais fácil: Use o operador unary +.

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

Isso converte o booleano em número;

style={ opacity: +!isFirstStep() }
Jose Velasco
fonte
4

Você pode fazer isso simplesmente estendendo o protótipo booleano

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

Não é muito fácil entender o que está acontecendo lá; portanto, uma versão alternativa seria

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

tendo feito o que você pode fazer coisas como

document.write(true.intval());

Quando uso booleanos para armazenar condições, costumo convertê-los em campos de bits. Nesse caso, acabo usando uma versão estendida da função prototype

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

com o qual você pode fazer

document.write(true.intval(2))

que produz 4 como sua saída.

DroidOS
fonte
4
let integerVariable = booleanVariable * 1;
Esger
fonte
1

Eu testei todos esses exemplos, fiz uma referência e, finalmente, recomendo que você escolha a mais curta, não afeta o desempenho.

Executado no servidor 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")

Resultado

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
DarckBlezzer
fonte
0

se você quiser um valor inteiro x, altere se 1 a 0 e se 0 a 1 você pode usar (x + 1)% 2

şevket Karayılan
fonte