Konwertuj wynik boolowski na liczbę / liczbę całkowitą

276

Mam zmienną, która przechowuje falselub true, ale muszę 0albo 1zamiast, odpowiednio. W jaki sposób mogę to zrobić?

hd.
źródło
8
Oto porównanie wydajności niektórych z dostarczonych technik: jsperf.com/conversion-from-boolean-to-number .
Sam
4
Użytkownicy Node.JS będą chcieli korzystać bool === true ? 1 : 0, ponieważ jest to zdecydowanie najszybszy w V8.
Qix - MONICA MISTREATED
3
lub po prostubool ? 1 : 0;
Atrahasis

Odpowiedzi:

343

JavaScript ma trójskładnikowego operatora, którego możesz użyć:

var i = result ? 1 : 0;
Andy Rose
źródło
7
Najlepsza odpowiedź. Czemu? Działa to na prawdomówność, która jest bardziej ogólna i akceptuje dowolny typ (ciąg, liczba itp.). Jednoargumentowa odpowiedź jest rzeczywiście sprytna, ale jeśli przekażę ciąg, zwraca NaN. Więc jeśli chcesz L33T i zagwarantować wejście, idź na mocz, inaczej podejmie test trójskładnikowy + test prawdy jest najlepszy.
gdibble
465

Użyj jednoargumentowego +operatora , który konwertuje swój operand na liczbę.

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

Pamiętaj oczywiście, że nadal powinieneś dezynfekować dane po stronie serwera, ponieważ użytkownik może wysłać dowolne dane do serwera, bez względu na to, co mówi kod po stronie klienta.

samotny dzień
źródło
50
Chociaż fajne (nigdy o tym nie myślałem), jest niesamowicie wolne (dokładnie 97% wolniej w Chrome). Uważać!
Qix - MONICA MISTREATED
5
Sprawdź tę wersję . Number()jest jeszcze wolniejszy.
Qix - MONICA MISTREATED
23
Wydaje się, że bool === true ? 1 : 0jest najszybszy, z bliską sekundą od bool | 0.
Qix - MONICA MISTREATED
1
Mnożenie (np. 3 * fałsz) wydaje się takie złe, ale działa. :) Dzięki!
mattsoave
1
@DerkJanSpeelman Fakt, że coś nie jest dozwolone w Typescript, nie oznacza, że ​​nie powinieneś tego robić w JavaScript. Są to różne (choć powiązane) języki.
samotny
119

Imho najlepszym rozwiązaniem jest:

fooBar | 0

Jest to używane w asm.js do wymuszenia typu całkowitego.

kralyk
źródło
Jeden z najszybszych; +1.
Qix - MONICA MISTREATED
3
Niezłe. Możesz także użyć „Boolean ^ 0”. OR lub XOR działa.
F8ER,
To nie zwróci 1liczby całkowitej, jeśli nie będzie fooBar?
ESR
58

Wolę korzystać z funkcji Numer . Pobiera obiekt i konwertuje go na liczbę.

Przykład:

var myFalseBool = false;
var myTrueBool = true;

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

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

Możesz to przetestować w jsFiddle .

René
źródło
3
Jak dotąd najlepsza odpowiedź. Oczywiście na dole. Tylko „zabiera obiekt” jest niewłaściwe.
Rudie,
2
Link do mdn jest znacznie lepszy niż w3schools (eeek!): Developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Olivvv
Myślę, że to najlepszy sposób, ponieważ jest łatwy do odczytania i ujawnia intencje.
Sam
3
Jest również najwolniej.
Qix - MONICA MISTREATED
45

Stworzyłem JSperf porównanie wszystkich sugerowanych odpowiedzi.

TL; DR - najlepsza opcja dla wszystkich obecnych przeglądarek to:

val | 0;

.

Aktualizacja:

Wygląda na to, że w dzisiejszych czasach wszystkie są dość identyczne, z wyjątkiem tego, że Number()funkcja jest najwolniejsza, a jednocześnie najlepsza val === true ? 1 : 0;.

Gal Talmor
źródło
2
Co ciekawe, trójskładnik jest teraz najszybszy w Chrome 64.0.3282 na macOS 10.13.3.
2540625
W tym czasie byłaby to najszybsza opcja. To różni się od tego, że jest to najlepsza opcja.
mikemaccana
41

Typowym sposobem na zrobienie tego byłoby:

Number(true) // 1
Number(false) // 0
Philip
źródło
2
Wreszcie przyzwoita odpowiedź. Dzięki.
Erik Campobadal,
30

Właśnie dzisiaj spotkałem ten skrót.

~~ (prawda)

~~ (fałsz)

Ludzie o wiele mądrzejsi niż potrafię wyjaśnić:

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

tonyjcamp
źródło
2
Ciekawy. Nauczyłem się dzisiaj czegoś nowego. Nie będę jednak używać tej techniki w żadnym projekcie, ponieważ może ona wprowadzić w błąd przyszłe ja lub członków drużyny.
nicholaides
1
hacky js to moja ulubiona. poważnie, +1
Todd
16

Gdy JavaScript oczekuje wartości liczbowej, ale zamiast tego otrzymuje wartość logiczną, konwertuje tę wartość logiczną na liczbę: odpowiednio prawda i fałsz zamieniają odpowiednio na 1 i 0. Możesz więc z tego skorzystać;

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

Dalsza lektura Konwersje typów Rozdział 3.8 Ostatecznego przewodnika po Javascript.

Charlie Lynch
źródło
13

Unary +operator zajmie się tym:

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

Naturalnie będziesz chciał to sprawdzić na serwerze przed przechowywaniem, więc i tak może to być bardziej rozsądne miejsce.

Gustav Barkefors
źródło
Zmieniłem komentarze na ===, ponieważ true == 1jest to prawdą nawet bez wyrażenia „jawna konwersja :-) true === 1zamiast tego jest fałszywe.
xanatos
13

Właśnie zajmowałem się tym problemem w jakimś pisanym przeze mnie kodzie. Moim rozwiązaniem było użycie bitowego i.

var j = bool & 1;

Szybszym sposobem radzenia sobie ze stałym problemem byłoby utworzenie funkcji. Jest bardziej czytelny dla innych ludzi, lepiej dla zrozumienia na etapie konserwacji i pozbywa się możliwości napisania czegoś złego.

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

var j = toInt(bool);

Edycja - 10 września 2014 r

Z jakiegoś powodu żadna konwersja przy użyciu operatora trójskładnikowego z operatorem identycznym do operatora nie jest szybsza w Chrome. Nie ma sensu, dlaczego jest szybszy, ale przypuszczam, że jest to jakaś optymalizacja niskiego poziomu, która ma sens gdzieś po drodze.

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

Sprawdź sam: http://jsperf.com/boolean-int-conversion/2

W FireFox i Internet Explorer korzystanie z opublikowanej wersji jest ogólnie szybsze.

Edycja - 14 lipca 2017 r

Okej, nie powiem ci, którego powinieneś, a czego nie powinieneś. Każda cholerna przeglądarka poruszała się w górę iw dół pod względem szybkości wykonywania każdej metody. W pewnym momencie Chrome miał lepszą wersję bitową i wersję niż inne, ale nagle stało się znacznie gorzej. Nie wiem co robią, więc zostawię to komu to obchodzi. Rzadko jest jakiś powód, aby martwić się o szybkość takiej operacji. Nawet na urządzeniach mobilnych jest to operacja nic.

Oto nowa metoda dodawania prototypu „toInt”, której nie można zastąpić.

Object.defineProperty(Boolean.prototype, "toInt", { value: function()
{
    return this & 1;
}});
Nicholas R. Grant
źródło
Mam dwa opinie negatywne dotyczące tego postu. Dlaczego nie wyjaśnisz, dlaczego to zrobiłeś? W przeciwnym razie jest to tylko głosowanie bez uzasadnienia.
Nicholas R. Grant,
1
99 razy więcej niż wyniki jsperf prowadzą cię na przedwczesną ścieżkę optymalizacji, optymalizując nanosekundy z pętli, kiedy powinieneś skupić się na tej brzydkiej instrukcji SQL. dzięki za udostępnienie kilku różnych sposobów podejścia do tego
RozzA
Jaka instrukcja SQL? Nie ma tu ani jednego zapytania. Jeśli masz na myśli JSPerf, łączyłem to z testu innej osoby. To nie jest moje. Szczerze mówiąc, nie dbam o aspekt wydajności, ponieważ jest to operacja nic. Stworzyłem własny język, który był prawie funkcjonalny identyczny z JS i pamiętam, że rzutowanie na int było głupią szybką operacją. Wspinaczka prototypowych łańcuchów nie była. Dlatego nadal polecam pierwszy sposób, w jaki to zrobiłem, z prostą funkcją, którą kompilator może wprowadzić.
Nicholas R. Grant,
kwestia SQL stanowi uogólnienie. dzięki za wgląd
RozzA
9

Możesz także dodać 0, użyć operatorów shift lub xor:

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

Mają one podobne prędkości jak odpowiedzi innych.

REMqb
źródło
6

W moim kontekście React Native, w którym otrzymuję wartość krycia z wartości logicznej, najprostszy sposób: użyj operatora unary +.

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

Konwertuje to wartość logiczną na liczbę;

style={ opacity: +!isFirstStep() }
Jose Velasco
źródło
4

Możesz to zrobić, po prostu rozszerzając prototyp logiczny

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

Nie jest łatwo zrozumieć, co się tam dzieje, więc byłaby to alternatywna wersja

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

po zrobieniu tego, co możesz zrobić

document.write(true.intval());

Kiedy używam booleanów do przechowywania warunków, często przekształcam je w pola bitowe, w którym to przypadku używam rozszerzonej wersji funkcji prototypowej

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

z którymi możesz zrobić

document.write(true.intval(2))

co daje 4 jako wynik.

DroidOS
źródło
4
let integerVariable = booleanVariable * 1;
Esger
źródło
1

Przetestowałem wszystkie te przykłady, zrobiłem test porównawczy i na koniec polecam wybrać krótszy, nie ma to wpływu na wydajność.

Uruchomiony na serwerze 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")

Wynik

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
źródło
0

jeśli chcesz zmienić wartość całkowitą x, jeśli 1 na 0 i jeśli 0 na 1, możesz użyć (x + 1)% 2

şevket Karayılan
źródło