Chuyển đổi kết quả boolean thành số / số nguyên


276

Tôi có một biến lưu trữ falsehoặc true, nhưng tôi cần 0hoặc 1thay vào đó, tương ứng. Tôi có thể làm cái này như thế nào?


8
Dưới đây là so sánh hiệu suất của một số kỹ thuật được cung cấp: jsperf.com/conversion-from-boolean-to-number .
Sam

4
Người dùng Node.JS sẽ muốn sử dụng bool === true ? 1 : 0, vì nó nhanh nhất trong V8.
Qix - MONICA ĐƯỢC PHÂN PHỐI 17/03/2016

3
hoặc chỉbool ? 1 : 0;
Atrahocation

Câu trả lời:


343

Javascript có một toán tử ternary bạn có thể sử dụng:

var i = result ? 1 : 0;

7
Câu trả lời tốt nhất. Tại sao? Điều này hoạt động dựa trên tính trung thực, khái quát hơn và chấp nhận bất kỳ loại nào (chuỗi, số, vân vân.) Câu trả lời đơn nhất thực sự thông minh, nhưng nếu tôi chuyển qua nó, nó sẽ trả về NaN. Vì vậy, nếu bạn muốn L33T và đảm bảo đầu vào, hãy đi tiểu, nếu không thì kiểm tra thử nghiệm ternary + thật là tốt nhất.
gdibble

465

Sử dụng các unary +nhà điều hành , chuyển đổi toán hạng của nó thành một số.

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

Tất nhiên, lưu ý rằng bạn vẫn nên vệ sinh dữ liệu ở phía máy chủ, bởi vì người dùng có thể gửi bất kỳ dữ liệu nào đến máy chủ của bạn, bất kể mã phía máy khách nói gì.


50
Mặc dù tuyệt vời (tôi chưa bao giờ nghĩ về điều này), nó rất chậm (chính xác là chậm hơn 97% trong Chrome). Hãy cảnh giác!
Qix - MONICA ĐƯỢC PHÂN PHỐI 17/03/2016

5
Kiểm tra sửa đổi này . Number()thậm chí còn chậm hơn
Qix - MONICA ĐƯỢC PHÂN PHỐI 17/03/2016

23
Nó xuất hiện bool === true ? 1 : 0là nhanh nhất, với một giây gần bool | 0.
Qix - MONICA ĐƯỢC PHÂN PHỐI 17/03/2016

1
Nhân (ví dụ 3 * sai) cảm thấy rất sai, nhưng nó hoạt động. :) Cảm ơn!
mattsoave

1
@DerkJanSpeelman Thực tế là một cái gì đó không được phép trong Bản mô tả không có nghĩa là bạn không nên làm điều đó trong Javascript. Chúng là các ngôn ngữ khác nhau (mặc dù liên quan).
cô đơn

119

Imho giải pháp tốt nhất là:

fooBar | 0

Điều này được sử dụng trong asm.js để buộc loại số nguyên.


Một trong những cách nhanh nhất; +1.
Qix - MONICA ĐƯỢC PHÂN PHỐI 17/03/2016

3
Đẹp một. Ngoài ra, bạn có thể sử dụng "Boolean ^ 0". HOẶC hoặc XOR hoạt động.
F8ER

Điều này sẽ không trả về một 1số nguyên nếu fooBar không?
ESR

58

Tôi thích sử dụng chức năng Số . Nó nhận một đối tượng và chuyển đổi nó thành một số.

Thí dụ:

var myFalseBool = false;
var myTrueBool = true;

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

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

Bạn có thể kiểm tra nó trong một jsFiddle .


3
Đây là câu trả lời tốt nhất cho đến nay. Ở dưới cùng của khóa học. Chỉ "nó mất một đối tượng" là không đúng.
Rudie

2
Liên kết đến MDN là tốt hơn nhiều so với w3schools (eeek!): Developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
Olivvv

Tôi nghĩ rằng đây là cách tốt nhất vì nó dễ đọc và tiết lộ ý định.
Sam

3
Nó cũng chậm nhất.
Qix - MONICA ĐƯỢC PHÂN BIỆT 18/03/2016

45

Tôi đã tạo một so sánh JSperf của tất cả các câu trả lời được đề xuất.

TL; DR - tùy chọn tốt nhất cho tất cả các trình duyệt hiện tại là:

val | 0;

.

Cập nhật:

Có vẻ như những ngày này tất cả chúng đều khá giống nhau, ngoại trừ Number()chức năng là chậm nhất, trong khi tốt nhất val === true ? 1 : 0;.


2
Điều thú vị là, ternary hiện nhanh nhất trong Chrome 64.0.3282 trên macOS 10.13.3.
2540625

Đó sẽ là lựa chọn nhanh nhất vào thời điểm đó. Đó là khác biệt từ nó là lựa chọn tốt nhất.
mikemaccana

41

Cách đánh máy để làm điều này sẽ là:

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

2
Cuối cùng một số câu trả lời đàng hoàng. Cảm ơn.
Erik Campobadal

30

Tôi vừa đi qua lối tắt này ngày hôm nay.

~ ~ (đúng)

~ ~ (sai)

Mọi người thông minh hơn tôi có thể giải thích:

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


2
Hấp dẫn. Tôi đã học được một cái gì đó mới ngày hôm nay. Mặc dù vậy, tôi sẽ không sử dụng kỹ thuật này trong bất kỳ dự án nào, bởi vì tiềm năng của nó gây nhầm lẫn cho tôi hoặc đồng đội trong tương lai.
nicholaides

1
hack js là fav của tôi. Nghiêm túc, +1
Todd

16

Khi JavaScript đang mong đợi một giá trị số nhưng nhận được một boolean thay vào đó, nó chuyển đổi boolean đó thành một số: true và false chuyển đổi thành 1 và 0 tương ứng. Vì vậy, bạn có thể tận dụng lợi thế này;

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

Đọc thêm Chuyển đổi loại Chương 3.8 của Hướng dẫn dứt khoát về Javascript.


13

Nhà +điều hành unary sẽ đảm nhận việc này:

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

Bạn sẽ tự nhiên muốn kiểm tra sự tỉnh táo này trên máy chủ trước khi lưu trữ nó, vì vậy đó có thể là một nơi hợp lý hơn để làm điều này dù thế nào đi nữa.


Tôi đã thay đổi các nhận xét thành ===, bởi vì true == 1nó đúng ngay cả khi "chuyển đổi rõ ràng :-) true === 1thay vào đó là sai.
xanatos

13

Tôi chỉ giải quyết vấn đề này trong một số mã tôi đang viết. Giải pháp của tôi là sử dụng một chút và.

var j = bool & 1;

Một cách nhanh hơn để giải quyết vấn đề liên tục sẽ là tạo một hàm. Người khác dễ đọc hơn, hiểu rõ hơn ở giai đoạn bảo trì và loại bỏ khả năng viết sai.

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

var j = toInt(bool);

Chỉnh sửa - ngày 10 tháng 9 năm 2014

Vì một số lý do, không có chuyển đổi nào sử dụng toán tử ternary giống hệt với toán tử nhanh hơn trong Chrome. Không có lý do tại sao nó nhanh hơn, nhưng tôi cho rằng đó là một loại tối ưu hóa cấp thấp có ý nghĩa ở đâu đó trên đường đi.

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

Tự kiểm tra: http://jsperf.com/boolean-int-conversion/2

Trong FireFox và Internet Explorer, sử dụng phiên bản tôi đã đăng thường nhanh hơn.

Chỉnh sửa - ngày 14 tháng 7 năm 2017

Được rồi, tôi sẽ không nói cho bạn biết bạn nên hay không nên sử dụng cái nào. Mỗi trình duyệt kỳ dị đã được tăng giảm trong việc họ có thể thực hiện thao tác nhanh như thế nào với mỗi phương thức. Chrome tại một thời điểm thực sự có bitwise & phiên bản hoạt động tốt hơn các phiên bản khác, nhưng sau đó nó đột nhiên tồi tệ hơn nhiều. Tôi không biết họ đang làm gì, vì vậy tôi sẽ để nó ở chỗ ai quan tâm. Hiếm khi có bất kỳ lý do nào để quan tâm đến việc một hoạt động như thế này được thực hiện nhanh như thế nào. Ngay cả trên thiết bị di động, nó không phải là một hoạt động.

Ngoài ra, đây là một phương pháp mới hơn để thêm nguyên mẫu 'toInt' không thể ghi đè.

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

Tôi đã có hai lượt tải xuống cho bài viết này. Tại sao bạn không giải thích lý do tại sao bạn đánh giá thấp nó. Nếu không, nó chỉ là một downvote mà không cần biện minh.
Nicholas R. Grant

1
99 lần kết quả của jsperf chỉ dẫn bạn đến con đường tối ưu hóa sớm, tối ưu hóa nano giây khỏi vòng lặp khi bạn nên tập trung vào câu lệnh SQL xấu xí đó. cảm ơn vì đã cung cấp một vài cách khác nhau để tiếp cận điều này
RozzA

Câu lệnh SQL nào? Không có một truy vấn nào ở đây. Nếu bạn đang đề cập đến JSPerf, tôi đã liên kết nó từ thử nghiệm của người khác. Nó không phải của riêng tôi. Tôi thực sự không quan tâm đến khía cạnh hiệu suất của việc này vì nó không phải là hoạt động. Tôi đã tạo ngôn ngữ của riêng mình gần giống với chức năng của JS và tôi nhớ rằng việc truyền sang int là một thao tác nhanh chóng ngu ngốc. Leo chuỗi nguyên mẫu là không. Đó là lý do tại sao tôi vẫn khuyên dùng cách đầu tiên tôi đã làm, với một hàm đơn giản có thể được trình biên dịch nội tuyến.
Nicholas R. Grant

điều SQL 'là một khái quát. cảm ơn vì sự sáng suốt
RozzA

9

Bạn cũng có thể thêm 0, sử dụng toán tử thay đổi hoặc xor:

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

Những cái này có tốc độ tương tự như những câu trả lời từ những người khác.


6

Trong ngữ cảnh của tôi, React Native nơi tôi đang nhận giá trị độ mờ từ boolean, cách dễ nhất: Sử dụng toán tử unary +.

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

Điều này chuyển đổi boolean thành số;

style={ opacity: +!isFirstStep() }

4

Bạn có thể làm điều này bằng cách mở rộng nguyên mẫu boolean

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

Không quá dễ hiểu những gì đang diễn ra ở đó nên một phiên bản thay thế sẽ là

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

đã làm mà bạn có thể làm những thứ như

document.write(true.intval());

Khi tôi sử dụng booleans để lưu trữ các điều kiện, tôi thường chuyển đổi chúng thành bitfield trong trường hợp tôi kết thúc bằng một phiên bản mở rộng của hàm nguyên mẫu

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

với những gì bạn có thể làm

document.write(true.intval(2))

mà tạo ra 4 là đầu ra của nó.




1

Tôi đã kiểm tra tất cả các ví dụ này, tôi đã làm một điểm chuẩn và cuối cùng tôi khuyên bạn nên chọn cái ngắn hơn, nó không ảnh hưởng đến hiệu suất.

Được chạy trong máy chủ 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")

Kết quả

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

0

nếu bạn muốn thay đổi giá trị x số nguyên nếu 1 thành 0 và nếu 0 thành 1, bạn có thể sử dụng (x + 1)% 2

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.