Converti il ​​risultato booleano in numero / intero


276

Ho una variabile che memorizza falseo true, ma ho bisogno 0o 1invece, rispettivamente. Come posso fare questo?


8
Ecco un confronto delle prestazioni di alcune delle tecniche fornite: jsperf.com/conversion-from-boolean-to-number .
Sam,

4
Gli utenti di Node.JS vorranno utilizzare bool === true ? 1 : 0, poiché è di gran lunga il più veloce in V8.
Qix - MONICA È STATA MISTREATA il

3
o semplicementebool ? 1 : 0;
Atrahasis,

Risposte:


343

Javascript ha un operatore ternario che puoi usare:

var i = result ? 1 : 0;

7
Migliore risposta. Perché? Funziona sulla verità, che è più generale e accetta qualsiasi tipo (stringa, numero, ecc.). La risposta unaria è davvero intelligente, ma se le passo una stringa restituisce NaN. Quindi, se vuoi L33T e garantire l'input, vai all'urario, altrimenti pensa che il test ternario + verità sia il migliore.
gdibble,

466

Utilizzare l' operatore unario+ , che converte il suo operando in un numero.

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

Si noti, ovviamente, che è comunque necessario disinfettare i dati sul lato server, poiché un utente può inviare qualsiasi dato al server, indipendentemente da ciò che dice il codice lato client.


50
Anche se fico (non ci avevo mai pensato), è incredibilmente lento (97% più lento in Chrome, per l'esattezza). Diffidare!
Qix - MONICA È STATA MISTREATA il

5
Dai un'occhiata a questa revisione . Number()è ancora più lento.
Qix - MONICA È STATA MISTREATA il

23
Sembra bool === true ? 1 : 0il più veloce, con un secondo vicino da bool | 0.
Qix - MONICA È STATA MISTREATA il

1
Moltiplicare (ad esempio 3 * false) sembra così sbagliato, ma funziona. :) Grazie!
mattsoave,

1
@DerkJanSpeelman Il fatto che qualcosa non sia permesso in Typescript non significa che non dovresti farlo in Javascript. Sono lingue diverse (anche se correlate).
lunedì

119

Imho la soluzione migliore è:

fooBar | 0

Questo è usato in asm.js per forzare il tipo intero.


Uno dei più veloci; +1.
Qix - MONICA È STATA MISTREATA il

3
Ben fatto. Inoltre potresti usare "Boolean ^ 0". OR o XOR funzionano.
F8ER,

Questo non restituirà un 1numero intero se FooBar non lo è?
ESR,

58

Preferisco usare la funzione Numero . Prende un oggetto e lo converte in un numero.

Esempio:

var myFalseBool = false;
var myTrueBool = true;

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

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

Puoi provarlo in un jsFiddle .


3
Questa è di gran lunga la risposta migliore. In fondo ovviamente. Solo "prende un oggetto" non è giusto.
Rudie,

2
Il collegamento a mdn è molto meglio di w3schools (eeek!): Developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Olivvv

Penso che questo sia il modo migliore perché è facile da leggere e rivelatore di intenzioni.
Sam,

3
È anche il più lento.
Qix - MONICA È STATA MISTREATA il

45

Ho creato un confronto JSperf di tutte le risposte suggerite.

TL; DR: l'opzione migliore per tutti i browser attuali è:

val | 0;

.

Aggiornare:

Sembra che in questi giorni siano tutti abbastanza identici, tranne per il fatto che la Number()funzione è la più lenta, mentre la migliore è val === true ? 1 : 0;.


2
È interessante notare che il ternario ora è il più veloce in Chrome 64.0.3282 su macOS 10.13.3.
2540625,

Sarebbe l'opzione più veloce, al momento. Questo è distinto dal fatto che è l'opzione migliore.
mikemaccana,

41

Il modo tipizzato per farlo sarebbe:

Number(true) // 1
Number(false) // 0

2
Finalmente una risposta decente. Grazie.
Erik Campobadal,


16

Quando JavaScript si aspetta un valore numerico ma riceve un valore booleano invece converte quel valore booleano in un numero: true e false vengono convertiti rispettivamente in 1 e 0. Quindi puoi approfittare di questo;

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

Ulteriori letture Conversioni di tipi Capitolo 3.8 della Guida definitiva a Javascript.


13

L' +operatore unario si occuperà di questo:

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

Avrai naturalmente bisogno di controllare la sanità mentale sul server prima di archiviarlo, quindi potrebbe essere comunque un posto più ragionevole per farlo.


Ho modificato i commenti in ===, perché true == 1è vero anche senza la "conversione esplicita :-) true === 1invece è falso.
xanatos

13

Stavo solo affrontando questo problema in qualche codice che stavo scrivendo. La mia soluzione era di usare un bit per bit e.

var j = bool & 1;

Un modo più rapido per affrontare un problema costante sarebbe quello di creare una funzione. È più leggibile da altre persone, meglio per la comprensione in fase di manutenzione e elimina il potenziale per scrivere qualcosa di sbagliato.

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

var j = toInt(bool);

Modifica - 10 settembre 2014

Nessuna conversione tramite Chrome con un operatore ternario identico all'operatore è più veloce in Chrome per qualche motivo. Non ha senso il motivo per cui è più veloce, ma suppongo che sia una sorta di ottimizzazione di basso livello che ha senso da qualche parte lungo la strada.

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

Prova tu stesso: http://jsperf.com/boolean-int-conversion/2

In FireFox e Internet Explorer, l'utilizzo della versione che ho pubblicato è generalmente più veloce.

Modifica - 14 luglio 2017

Okay, non ti dirò quale dovresti o non dovresti usare. Ogni browser impazzito è andato su e giù in quanto velocemente può fare l'operazione con ogni metodo. Chrome a un certo punto aveva effettivamente la versione bit per bit e migliore degli altri, ma improvvisamente è andata molto peggio. Non so cosa stiano facendo, quindi lo lascerò a chi se ne frega. Raramente ci sono motivi per preoccuparsi di quanto velocemente viene eseguita un'operazione come questa. Anche sul cellulare è un'operazione nulla.

Inoltre, ecco un nuovo metodo per aggiungere un prototipo 'toInt' che non può essere sovrascritto.

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

Ho avuto due voti negativi per questo post. Perché non spieghi perché l'hai sottovalutato. Altrimenti è solo un downvote senza giustificazione.
Nicholas R. Grant,

1
99 volte i risultati di jsperf ti portano solo sul percorso di ottimizzazione prematura, ottimizzando i nanosecondi fuori da un ciclo quando dovresti invece concentrarti su quella brutta istruzione SQL. grazie per aver fornito diversi modi per affrontare questo
problema

Quale istruzione SQL? Non c'è una sola query qui. Se ti riferisci a JSPerf, lo stavo collegando dal test di qualcun altro. Non è mio. Onestamente non mi interessa l'aspetto prestazionale di questo dato che si tratta di un'operazione nulla. Ho creato il mio linguaggio che era quasi identico a quello di JS e ricordo che il casting su int era un'operazione incredibilmente veloce. Le catene prototipo di arrampicata non lo erano. Questo è il motivo per cui consiglierei ancora il primo modo in cui l'ho fatto, con una semplice funzione che può essere sottolineata dal compilatore.
Nicholas R. Grant,

la cosa SQL era una generalizzazione. grazie per l'intuizione
RozzA

9

Puoi anche aggiungere 0, usare gli operatori shift o xor:

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

Questi hanno velocità simili a quelle delle risposte degli altri.


6

Nel mio contesto, React Native, dove sto ottenendo il valore di opacità dal valore booleano, il modo più semplice: utilizzare unario + operatore.

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

Questo converte il valore booleano in numero;

style={ opacity: +!isFirstStep() }

4

Puoi farlo semplicemente estendendo il prototipo booleano

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

Non è troppo facile capire cosa sta succedendo lì, quindi sarebbe una versione alternativa

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

dopo aver fatto ciò che puoi fare cose come

document.write(true.intval());

Quando uso i booleani per memorizzare le condizioni, li converto spesso in bitfield, nel qual caso finisco per usare una versione estesa della funzione prototipo

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

con cui puoi fare

document.write(true.intval(2))

che produce 4 come output.


4
let integerVariable = booleanVariable * 1;


1

Ho testato tutti questi esempi, ho fatto un benchmark e infine ti consiglio di scegliere quello più corto, non influisce sulle prestazioni.

Eseguito nel server 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")

Risultato

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.