Có cách nào tốt hơn để viết v = (v == 0? 1: 0); [đóng cửa]


465

Tôi muốn chuyển một biến trong khoảng từ 0 đến 1. Nếu là 0 Tôi muốn đặt nó thành 1, nếu không thì tôi muốn đặt nó thành 0.

Đây là một hoạt động cơ bản mà tôi thường viết nên tôi muốn điều tra cách thức ngắn nhất, rõ ràng nhất có thể để thực hiện. Đây là điều tốt nhất của tôi cho đến nay:

v = (v == 0 ? 1 : 0);

Bạn có thể cải thiện điều này?

Chỉnh sửa: câu hỏi là hỏi làm thế nào để viết câu lệnh trên trong một vài ký tự trong khi vẫn giữ được sự rõ ràng - làm thế nào đây 'không phải là một câu hỏi thực sự'? Đây không phải là một bài tập golf mã, mặc dù một số câu trả lời thú vị đã được đưa ra từ những người tiếp cận nó như golf - thật tuyệt khi thấy golf được sử dụng theo cách xây dựng và kích thích tư duy.


20
Điều này có vẻ đơn giản / rõ ràng / ngắn đối với tôi.
Mob

136
mánh khóe:v = +!v;
jAndy

48
Nếu 'tốt hơn' cũng có nghĩa là 'nhanh hơn': jsperf.com/v-0-1-0 .
pimvdb

7
@Mobinga: +1. Điều này là đơn giản như nó sẽ nhận được. Tất cả các câu trả lời khác tôi thấy là khó hiểu, và một số trong số chúng thay đổi logic; giới thiệu lỗi.
Ian Boyd

8
@holodoc Một giải pháp tốt hơn để bày tỏ ý kiến ​​của bạn sẽ là tạo ra một câu trả lời nói rằng bạn cảm thấy bản gốc là cách tốt nhất và giải thích rõ hơn TẠI SAO bạn cảm thấy đó là trường hợp. điều đó cũng cho phép người khác dễ dàng đối mặt với câu trả lời của bạn bằng cách bỏ phiếu.
Chuck van der Linden

Câu trả lời:


721

Bạn chỉ có thể sử dụng:

v = 1 - v;

Tất nhiên điều này giả định rằng biến được khởi tạo đúng, tức là nó chỉ có giá trị 0 hoặc 1.

Một phương pháp khác ngắn hơn nhưng sử dụng toán tử ít phổ biến hơn:

v ^= 1;

Biên tập:

Để rõ ràng; Tôi chưa bao giờ tiếp cận câu hỏi này như mã golf, chỉ để tìm một cách ngắn để thực hiện nhiệm vụ mà không sử dụng bất kỳ thủ thuật che khuất nào như tác dụng phụ của các nhà khai thác.


206
Đây là những dòng mã đẹp, như thủy tinh cắt tinh xảo hoặc hoa phong lan quý hiếm. Tôi thích cách bạn đã tiếp cận trực tiếp qua lớp logic và xử lý trực tiếp toán học 1 và 0 với các hoạt động tối ưu nhất có thể. Tôi sẽ sử dụng những thứ này trong các dự án của riêng tôi, nhưng thật không may khi tôi cần các đồng nghiệp hiểu mã, tôi sẽ phải mặc định theo cách tiếp cận dựa trên logic hơn. Cảm ơn bạn mặc dù, câu trả lời của bạn đã làm cho ngày của tôi.
Ollie Glass

37
Bạn luôn có thể thêm một bình luận cho biết những gì mã làm.
Prusse

25
@Kevin: không đúng vì điều này rõ ràng không trả lời câu hỏi như đã hỏi. Các q nói "Tôi muốn chuyển một biến trong khoảng từ 0 đến 1." Một cách giải thích rất hợp lý là điều này ngụ ý rằng giá trị của biến đã là 0 hoặc 1. Việc giải thích / giới hạn này được đưa ra rõ ràng trong câu trả lời. Những gì trên thế giới bạn có thể phản đối?
LarsH

50
@Matthew để nói rằng một người không tìm thấy v ^= 1rõ ràng nên dừng lập trình là một chút khắc nghiệt tôi nghĩ. Như đã nói trước đây, nó không phải là một trong những toán tử phổ biến hơn và nó không làm điều tương tự như v = v ^ 1. Ngoài ra toán tử có nghĩa là một cái gì đó hoàn toàn khác nhau trong các ngôn ngữ khác nhau (VB). Có, một cái nhìn nhanh sẽ cho bạn biết rằng nó là toán tử XOR và bạn sẽ hiểu nó đang làm gì, nhưng với nhiều người nó có thể không rõ ràng ngay từ cái nhìn đầu tiên. Tôi không nghĩ điều đó có nghĩa là bạn cần nghỉ việc.
JD Isaacks

80
Nếu bạn lưu 15 ký tự bằng cách viết này nhưng sau đó sử dụng 40 ký tự nhận xét để giải thích thì đó có thực sự là một cải tiến?
Michael Myers

343

0là một falsegiá trị và 1là một truegiá trị.

v = (v ? 0 : 1);

Nếu bạn hài lòng khi sử dụng truefalsethay vì số

v = !v;

hoặc nếu chúng phải là số:

v = +!v; /* Boolean invert v then cast back to a Number */

55
chỉ cần đặt sự kỳ diệu +trước đó !. Ôi thật là bẩn quá! nhưng tuyệt vời: p
jAndy

1
@Quentin - điều này sẽ phá vỡ mã của anh chàng nếu anh ta có switch(v){ case 0 ...hoặc nếu (v == 0) hoặc nếu v === 0. Bạn đang thay đổi kết quả của mình ngoài cách tiếp cận của anh ta ....
Brian

34
Tạo một nụ cười của nó : ({v :+! v}).v.
pimvdb

17
@Brian: không phải với +dấu hiệu ma thuật đó ! ¯ \ _ (ツ) _ / ¯
jAndy

11
+1 cho v = (v ? 0 : 1)JS rõ ràng và thành ngữ.
Bennett McElwee

200

v = (v + 1) % 2và nếu bạn cần để chu kỳ thông qua giá trị hơn chỉ cần thay đổi 2cho (n + 1). Nói rằng bạn cần chu kỳ 0,1,2 chỉ cần làm v = (v + 1) % 3.


2
Tôi yêu chu kỳ! Điều đó thực sự thông minh.
Ollie Glass

16
+1 để suy nghĩ về việc chuyển đổi như một chu kỳ. Đơn giản xem xét làm thế nào nó linh hoạt.
Guffa

3
+1 để cung cấp một giải pháp mô-đun cũng mạnh mẽ. Trong thực tế, bạn có thể muốn sử dụng một constbiến thay cho các số ma thuật 2, 3, ...
oosterwal

2
Cách ngắn hơn (tin tặc): ++v % 3nếu bạn muốn chuyển qua 0, 1, 2
haraldmartin

75

Bạn có thể viết một hàm cho nó và sử dụng nó như sau:

v = inv(v)


30
+1 Tôi hoàn toàn đồng ý đây là giải pháp sạch nhất (... nhưng sau đó là những gì có trong invchức năng: P)
Lea Hayes

4
Tôi ước tôi có thể đưa ra câu trả lời này nhiều hơn là chỉ +1. Nếu mã phổ biến không rõ ràng, nó sẽ được bọc trong một hàm với một tên mô tả.
TehShrike

11
@TehShrike bạn có coi invlà một cái tên mô tả không?
Bennett McElwee

3
@Bennett McElwee: inv = đảo ngược. Luôn luôn có vẻ như là một từ viết tắt phổ biến với tôi.
Daniel

51
Tại sao lại viết tắt nó, gọi nó là 'đảo ngược' hoặc 'chuyển đổi' và có thể đọc được mã. không phải như thể chúng ta đang cố gắn những thứ này vào một punchcard 80 cột hay thứ gì đó.
Chuck van der Linden

50

Nếu bạn không quan tâm đến bất kỳ khả năng nào khác ngoài 1:

v = v ? 0 : 1;

Trong trường hợp trên, v sẽ kết thúc bằng 1 nếu v là 0, sai, không xác định hoặc null. Hãy cẩn thận khi sử dụng cách tiếp cận này - v sẽ là 0 ngay cả khi v là "hello world".


2
Điều đó sẽ không lật giá trị. Bạn có ý nghĩa v = v ? 0 : 1.
Guffa

3
@Guffa - +1 để bắt chứng khó đọc của tôi ...
Brian

3
Đây là câu trả lời dựa trên logic yêu thích của tôi mà tôi có thể sử dụng với đồng nghiệp (Tôi đang xem câu trả lời của @ Guffa là dựa trên số). Tôi thích cách bạn đã thực hiện bài kiểm tra không cần thiết (v == 0) và bỏ dấu ngoặc, tước nó xuống số lượng ký tự tối thiểu tuyệt đối. Cảm ơn bạn.
Ollie Glass

1
Tôi cũng là một fan hâm mộ lớn của câu trả lời của @ Guffa - theo lời của skynard lynard, hãy giữ cho nó đơn giản;)
Brian

2
+1 để hiểu các giá trị "trung thực".
zzzzBov

44

Các dòng như v = 1 - v, v ^= 1hoặcv= +!v tất cả sẽ hoàn thành công việc, nhưng họ coi những gì tôi sẽ đề cập đến như hacks. Đây không phải là những dòng mã đẹp, nhưng thủ thuật rẻ tiền để có hiệu quả như mong muốn. 1 - vkhông giao tiếp "chuyển đổi giá trị từ 0 đến 1". Điều này làm cho mã của bạn ít biểu cảm hơn và giới thiệu một địa điểm (mặc dù là một địa điểm nhỏ) nơi một nhà phát triển khác sẽ phải phân tích mã của bạn.

Thay vào đó là một chức năng như v = toggle(v)truyền đạt ý định trong nháy mắt nhanh nhất.


8
-1, nghiêm túc, v=1-vkhông giao tiếp chuyển đổi?
Blindy

22
1-vcó thể giao tiếp thực sự chuyển đổi, nhưng đó là điều duy nhất nó giao tiếp. Ví dụ, nó cũng có thể giao tiếp một dòng có 0 tại v=1hoặc một phép biến đổi phản chiếu tập trung tại v=0.5. Theo nghĩa này nó tương đối mơ hồ. Đúng là biết rằng vchỉ có thể 0hoặc 1giới hạn ý nghĩa dự định của nó, nhưng điều đó buộc các nhà phát triển khác (hoặc bản thân tương lai của bạn) phải hiểu bối cảnh đó trước khi có thể hiểu được dòng đơn giản này. Bạn không thể rõ ràng hơn nhiềuv = toggle(v)
Ray

10
v ^= 1là hoàn toàn rõ ràng nếu bạn hiểu các hoạt động logic, tuy nhiên, bạn đã tốt hơn nếu bạn là một lập trình viên. Tôi nghĩ đó là sự khác biệt giữa điều đó và v=1-v; một hoạt động logic và một hoạt động số học, và chúng tôi đang cố gắng thể hiện một khái niệm logic không phải là một hoạt động toán học.
Matthew Đọc

6
@Matthew Đọc: Đây là một tuyên bố tuyệt vời, tóm tắt những suy nghĩ của tôi: "chúng tôi đang cố gắng thể hiện một khái niệm logic chứ không phải là một toán học." Thậm chí v ^= 1có một số sự mơ hồ, mặc dù, vì nó có thể được hiểu là một bitwise-xor.
Ray

6
Đối với các lập trình viên (và vâng, tôi có nghĩa là những người đam mê như chúng tôi), những điều này khá rõ ràng. Chúng không phải là hack, bởi vì chúng là những giải pháp tao nhã do sự đơn giản của chúng.
gion_13

38

( Tính trung thực và tính toàn vẹn về mặt toán học - với số phiếu bầu cho "câu trả lời" này - đã khiến tôi phải chỉnh sửa câu trả lời này. bất kỳ lời giải thích nào dường như trái với mục đích. Tuy nhiên, các ý kiến ​​đang nói rõ rằng tôi nên rõ ràng để tránh hiểu lầm. )

Câu trả lời ban đầu của tôi:

Từ ngữ của phần này của đặc điểm kỹ thuật:

Nếu là 0, tôi muốn đặt thành 1, nếu không thì đặt thành 0.

ngụ ý rằng giải pháp chính xác nhất là:

v = dirac_delta(0,v)

Đầu tiên, lời thú nhận: Tôi đã làm cho các chức năng delta của tôi bị nhầm lẫn. Đồng bằng Kronecker sẽ phù hợp hơn một chút, nhưng không nhiều như tôi muốn một cái gì đó độc lập với miền (đồng bằng Kronecker chủ yếu chỉ được sử dụng cho số nguyên). Nhưng tôi thực sự không nên sử dụng các hàm delta, tôi nên nói:

v = characteristic_function({0},v)

Hãy để tôi làm rõ. Nhớ lại rằng một chức năng là một triple, (X, Y, f) , nơi XY là bộ (gọi là miềncodomain tương ứng) và f là một quy tắc chuyển nhượng một phần tử của Y để mỗi phần tử của X . Chúng ta thường viết ba (X, Y, f)f: X → Y . Cho một tập hợp con của X , giả sử A , có một hàm đặc trưng là hàm χ A : X → {0,1} (nó cũng có thể được coi là một hàm cho một tên miền lớn hơn như hoặc). Hàm này được xác định theo quy tắc:

χ A (x) = 1 nếu x ∈ Aχ A (x) = 0 nếu x ∉ Một .

Nếu bạn thích các bảng chân lý, thì đó là bảng chân lý cho câu hỏi "Phần tử x của X có phải là phần tử của tập hợp con A không?".

Vì vậy, từ định nghĩa này, rõ ràng hàm đặc trưng là thứ cần thiết ở đây, với X một số tập lớn chứa 0 và A = {0} . Đó là những gì tôi nên viết.

Và như vậy để chức năng delta. Đối với điều này, chúng ta cần biết về tích hợp. Hoặc bạn đã biết nó, hoặc bạn không biết. Nếu bạn không, không có gì tôi có thể nói ở đây sẽ cho bạn biết về những rắc rối của lý thuyết, nhưng tôi có thể tóm tắt một câu. Một thước đo trên tập X về bản chất là "cần thiết để làm cho mức trung bình hoạt động". Điều đó có nghĩa là nếu chúng ta có một tập X và một số đo μ trên tập hợp đó thì có một lớp các hàm X → , được gọi là các hàm có thể đo được mà biểu thức X f dμ có nghĩa và theo nghĩa mơ hồ nào đó, "trung bình" của f trên X .

Đưa ra một thước đo trên một tập hợp, người ta có thể định nghĩa một "thước đo" cho các tập hợp con của tập hợp đó. Điều này được thực hiện bằng cách gán cho một tập hợp con tích phân của hàm đặc trưng của nó (giả sử rằng đây là hàm có thể đo được). Điều này có thể là vô hạn, hoặc không xác định (hai là khác nhau tinh tế).

Có rất nhiều biện pháp xung quanh, nhưng có hai biện pháp quan trọng ở đây. Một là số đo chuẩn trên đường thẳng thực, ℝ. Đối với biện pháp này, sau đó f dμ là khá nhiều những gì bạn nhận được giảng dạy trong nhà trường (là calculus vẫn dạy trong nhà trường?): Tổng hợp hình chữ nhật nhỏ và mất độ rộng nhỏ hơn và nhỏ hơn. Trong biện pháp này, số đo của một khoảng là chiều rộng của nó. Số đo của một điểm là 0.

Một biện pháp quan trọng khác, hoạt động trên bất kỳ tập hợp nào , được gọi là thước đo điểm . Nó được định nghĩa sao cho tích phân của hàm là tổng các giá trị của nó:

X f dμ = ∑ x fX f (x)

Biện pháp này gán cho mỗi đơn vị đặt biện pháp 1. Điều này có nghĩa là một tập hợp con có số đo hữu hạn khi và chỉ khi nó là hữu hạn. Và rất ít chức năng có tích phân hữu hạn. Nếu một hàm có tích phân hữu hạn, nó phải khác không chỉ trên một số điểm có thể đếm được . Vì vậy, phần lớn các hàm mà bạn có thể biết không có tích phân hữu hạn theo biện pháp này.

Và bây giờ đến chức năng delta. Hãy có một định nghĩa rất rộng. Chúng tôi có một không gian đo (X, μ) (vì vậy đó là một tập hợp với một biện pháp trên đó) và một yếu tố a ∈ X . Chúng tôi "định nghĩa" hàm delta (tùy thuộc vào a ) là "hàm" δ a : X → với tính chất δ a (x) = 0 nếu x ≠ aX δ a dμ = 1 .

Thực tế quan trọng nhất về vấn đề này để nắm giữ điều này là: Hàm delta không cần phải là một hàm . Người ta không định nghĩa đúng: Tôi đã không nói gì delta một (a) là.

Những gì bạn làm vào thời điểm này phụ thuộc vào bạn là ai. Thế giới ở đây chia thành hai loại. Nếu bạn là một nhà toán học, bạn nói như sau:

Được rồi, do đó, hàm delta có thể không được xác định. Chúng ta hãy xem xét các thuộc tính giả thuyết của nó và xem liệu chúng ta có thể tìm thấy một ngôi nhà thích hợp cho nó ở nơi nó được xác định hay không. Chúng tôi có thể làm điều đó, và chúng tôi kết thúc với phân phối . Đây không phải là các hàm (nhất thiết), nhưng là những thứ hoạt động giống như các hàm và chúng ta thường có thể làm việc với chúng như thể chúng là các hàm; nhưng có một số thứ nhất định mà họ không có (chẳng hạn như "giá trị") vì vậy chúng tôi cần phải cẩn thận.

Nếu bạn không phải là nhà toán học, bạn nói như sau:

Được rồi, do đó, hàm delta có thể không được xác định đúng. Ai nói vậy? Một nhóm các nhà toán học? Mặc kệ họ! Họ biết gì?

Bây giờ đã xúc phạm khán giả của tôi, tôi sẽ tiếp tục.

Các đồng bằng Dirac thường được lấy là hàm delta của một điểm (thường 0) trong dòng sản với biện pháp tiêu chuẩn của nó. Vì vậy, những người đang phàn nàn trong các ý kiến ​​về tôi không biết đồng bằng của tôi đang làm như vậy bởi vì họ đang sử dụng định nghĩa này. Đối với họ, tôi xin lỗi: mặc dù tôi có thể luồn lách ra khỏi điều đó bằng cách sử dụng biện pháp phòng thủ của Nhà toán học (như được phổ biến bởi Humpty Dumpty : chỉ đơn giản là xác định lại mọi thứ sao cho chính xác), đó là một hình thức xấu để sử dụng một thuật ngữ chuẩn để hiểu điều gì đó khác.

Nhưng có một hàm delta mà không làm những gì tôi muốn nó phải làm gì và đó là điều mà chính tôi cần ở đây. Nếu tôi có một điểm đo trên một tập hợp X sau đó một chức năng chính hãng δ một : X → ℝ mà đáp ứng các tiêu chí cho một hàm delta. Điều này là do chúng ta đang tìm kiếm một hàm X → bằng 0 ngoại trừ tại a và sao cho tổng của tất cả các giá trị của nó là 1. Hàm này rất đơn giản: phần thông tin bị thiếu duy nhất là giá trị của nó tại a , và để có được tổng bằng 1, chúng ta chỉ cần gán cho nó giá trị 1. Đây không phải là hàm nào khác ngoài {a} . Sau đó:

X δ a dμ = ∑ x ∈ X δ a (x) = δ a (a) = 1.

Vì vậy, trong trường hợp này, đối với một tập hợp đơn, hàm đặc trưng và hàm delta đồng ý.

Tóm lại, có ba họ "chức năng" ở đây:

  1. Các chức năng đặc trưng của bộ singleton,
  2. Các hàm delta
  3. Các hàm delta Kronecker.

Thứ hai trong số này là tổng quát nhất vì bất kỳ cái nào khác là một ví dụ về nó khi sử dụng thước đo điểm. Nhưng thứ nhất và thứ ba có lợi thế là chúng luôn là các chức năng chính hãng. Thứ ba thực sự là một trường hợp đặc biệt của trường hợp thứ nhất, đối với một họ miền cụ thể (số nguyên hoặc một số tập hợp con).

Vì vậy, cuối cùng, khi tôi ban đầu đã viết câu trả lời tôi đã không suy nghĩ đúng (tôi sẽ không đi xa như vậy để nói rằng tôi đã nhầm lẫn , như tôi hy vọng tôi vừa chứng minh tôi làm biết những gì tôi đang nói về việc khi nào Tôi thực sự nghĩ đầu tiên, tôi chỉ không nghĩ nhiều). Ý nghĩa thông thường của đồng bằng dirac không phải là điều mong muốn ở đây, nhưng một trong những điểm trong câu trả lời của tôi là miền đầu vào không được xác định nên đồng bằng Kronecker cũng sẽ không đúng. Do đó, câu trả lời toán học tốt nhất (mà tôi đang hướng tới) sẽ là hàm đặc trưng .

Tôi hy vọng rằng tất cả đã rõ ràng; và tôi cũng hy vọng rằng tôi sẽ không bao giờ phải viết một đoạn toán học nữa bằng cách sử dụng các thực thể HTML thay vì các macro TeX!


37
+1 - Nếu tôi có thể hạ cấp Quentin vì không biết hàm dirac_delta thì tôi sẽ làm. Tôi muốn biết anh ấy học trường đại học nào vì tôi không nghĩ tôi sẽ thuê bất cứ ai từ đó nếu họ thậm chí không biết điều gì đó cơ bản cho xử lý kỹ thuật số. Tôi sẽ đánh giá thấp hơn Quentin vì anh ta không thể nắm bắt được chút hài hước mà bạn đang cố gắng.
Dunk

23
Nếu tôi đánh giá thấp mọi câu trả lời tôi không hiểu ... tôi sẽ đánh giá thấp rất nhiều câu trả lời.
Seamus

4
Xin chào Andrew, đã được một lúc rồi.
Tim Down

4
@Tim: Thật đau buồn, vậy là có! Và Giám mục Bermuda như thế nào? (Tôi có nhớ đúng không?) Tôi đoán chủ đề bình luận này không phải là nơi tốt nhất để bắt kịp, mặc dù ... 17 năm, phải không?
Andrew Stacey

3
@ Cԃ ա ԃ "Câu trả lời này đã thất bại ..." thở dài . Bạn đã đọc rằng tôi là một nhà toán học, phải không? Câu trả lời này hoạt động hoàn hảo cho một lập trình viên hình cầu trong chân không vì vậy tôi không biết bạn đang phàn nàn về điều gì.
Andrew Stacey

35

Bạn có thể làm

v = Math.abs(--v);

Phần giảm đặt giá trị thành 0 hoặc -1, sau đó Math.abschuyển đổi -1 thành +1.


27
Điều này đã biến thành một cuộc thi 'Tạo ra 10000 cách để thực hiện một nhiệm vụ đơn giản'. Và tôi thích tất cả các cách haha.
Josh

27
v = Math.round(Math.sin(Math.PI/(v+3)));
Benoit

15
@Benoit - công thức của bạn bằng 1 cho cả v = 0 và v = 1. Điều này là chính xác mặc dù! v = Math.round(Math.cos(Math.PI/((v*2+1)+2)-2*v));: D
Teo.sk

2
Điều đó sẽ không bao giờ thay đổi giá trị. Nếu v = 1sau v = Math.Abs(-1)đó là +1. Nếu v = 0sau v = Math.Abs(-0)đó là 0.
Paul

1
+1 Và đây là một cái khác của tôi ... Grr.
đệ quy

34

nói chung bất cứ khi nào bạn cần chuyển đổi giữa hai giá trị, bạn chỉ có thể trừ giá trị hiện tại khỏi tổng của hai giá trị chuyển đổi:

    0,1 -> v = 1 - v
    1,2 -> v = 3 - v
    4,5 -> v = 9 - v 

2
Điều này là thú vị và sáng tạo nhưng có khả năng nguy hiểm. Nếu vbị hỏng, nó sẽ đột nhiên bắt đầu chuyển đổi giữa hai giá trị khác nhau. (Chỉ cần một cái gì đó để xem xét ...)
oosterwal

1
+1 cho ý tưởng thú vị. không phải là OP hay bất kỳ ai khác thực sự sẽ sử dụng nó trong trường hợp này, nhưng thông tin này sẽ tồn tại ở đâu đó trong não mãi mãi.
Shimmy Weitzhandler

3
@oosterwal: Sau đó, chắc chắn vấn đề nằm ở tham nhũng ...
GManNickG

@GManNickG: Sớm hay muộn dữ liệu sẽ xảy ra vì vậy chúng tôi cần phải nhận thức được hậu quả của việc không phát hiện ra nó. Nếu vthường được sử dụng để thực hiện luân phiên hai trạng thái từ danh sách ba trạng thái trở lên, thì tham nhũng vcó thể khiến chương trình thực hiện luân phiên hai trạng thái hoàn toàn khác nhau - điều này có thể dẫn đến kết quả không mong muốn và không mong muốn. Bài học rút ra từ điều này là: Luôn thực hiện kiểm tra tính hợp lý trên dữ liệu của bạn.
oosterwal

33

Nếu nó phải là số nguyên 1 hoặc 0, thì cách bạn đang làm là tốt, mặc dù dấu ngoặc đơn không cần thiết. Nếu những cái này được sử dụng làm booleans, thì bạn có thể làm:

v = !v;

10
Kết quả này có phải là "v" của Ollie được đặt thành kết quả boolean, không phải là số nguyên không?
Brian

12
Có nó sẽ, và tôi đã cảnh báo rằng trong câu trên dòng mã. Nếu những thứ này được sử dụng làm
booleans

23
v = v == 0 ? 1 : 0;

Là đủ !


7
Nhiều ý kiến ​​hơn là một câu trả lời, bạn có nghĩ vậy không?
Brian

16
@Brian: 'tốt hơn' là tất cả về ý kiến ​​thực sự.
pimvdb

3
Tôi thích cách bạn lấy dấu ngoặc ra - loại bỏ một vài ký tự!
Ollie Glass

9
@Brian: " Câu trả lời " là "Không, không có cách viết nào hay hơn v = (v==0 ? 1 : 0);" . Mọi người khác đang tìm cách chơi golf khác nhau; và không thực sự trả lời câu hỏi. Đó là lý do tại sao tôi bỏ phiếu cho câu trả lời này.
Ian Boyd

19

Danh sách các giải pháp

Có ba giải pháp tôi muốn đề xuất. Tất cả trong số họ chuyển đổi bất kỳ giá trị cho 0(nếu 1, truevv) hoặc 1(nếu 0, false, nullvv):

  • v = 1*!v
  • v = +!v
  • v = ~~!v

và một bổ sung, đã được đề cập, nhưng thông minh và nhanh chóng (mặc dù chỉ hoạt động cho 0s và 1s):

  • v = 1-v

Giải pháp 1

Bạn có thể sử dụng giải pháp sau:

v = 1*!v

Điều này trước tiên sẽ chuyển đổi số nguyên sang boolean ngược lại ( 0đến Truevà bất kỳ giá trị nào khác thành False), sau đó sẽ coi nó là số nguyên khi nhân với 1. Kết quả là 0sẽ được chuyển đổi thành 1và bất kỳ giá trị nào khác thành0 .

Để chứng minh hãy xem jsfiddle này và cung cấp bất kỳ giá trị nào bạn muốn kiểm tra: jsfiddle.net/rH3g5/

Kết quả như sau:

  • -123 sẽ chuyển đổi thành số nguyên 0,
  • -10 sẽ chuyển đổi thành số nguyên 0,
  • -1 sẽ chuyển đổi thành số nguyên 0,
  • 0 sẽ chuyển đổi thành số nguyên 1,
  • 1 sẽ chuyển đổi thành số nguyên 0,
  • 2 sẽ chuyển đổi thành số nguyên 0,
  • 60sẽ chuyển đổi thành số nguyên 0,

Giải pháp 2

Như mblase75 đã lưu ý, jAndy có một số giải pháp khác hoạt động như của tôi:

v = +!v

Đầu tiên, nó cũng tạo boolean từ giá trị ban đầu, nhưng sử dụng +thay vì 1*chuyển đổi nó thành số nguyên. Kết quả hoàn toàn giống nhau, nhưng ký hiệu ngắn hơn.

Giải pháp 3

Cách tiếp cận khác là sử dụng ~~toán tử:

v = ~~!v

Nó khá phổ biến và luôn chuyển đổi thành số nguyên từ boolean.


Trong JavaScript, bạn có thể thêm tiền tố vào một biến +để chuyển đổi nó thành một số, do đó, +!vtương đương với giải pháp của bạn (giải pháp của jAndy trong các bình luận của OP).
Blazemonger

@ mblase75: Có, bạn đã đúng khi 1*có thể +chuyển đổi boolean thành số nguyên. Mọi thứ khác trong câu trả lời của tôi vẫn giữ nguyên. Câu trả lời của jAndy là đúng, nhưng của tôi thì chi tiết hơn. Tôi sẽ thêm giải pháp của anh ấy / cô ấy vào câu trả lời của tôi.
Tadeck

@Tadeck +1 cho ý tưởng hay.
Shimmy Weitzhandler

17

Để tổng hợp một câu trả lời khác, một nhận xét và ý kiến ​​của riêng tôi, tôi đề nghị kết hợp hai điều:

  1. Sử dụng một chức năng để chuyển đổi
  2. Bên trong chức năng này sử dụng một triển khai dễ đọc hơn

Đây là chức năng mà bạn có thể đặt trong thư viện hoặc có thể gói nó trong Plugin cho một Khung Javascript khác.

function inv(i) {
  if (i == 0) {
    return 1
  } else {
    return 0;
  }
}

Và cách sử dụng chỉ đơn giản là:

v = inv(v);

Những ưu điểm là:

  1. Không sao chép mã
  2. Nếu bạn hoặc bất kỳ ai đọc lại điều này trong tương lai, bạn sẽ hiểu mã của mình trong thời gian tối thiểu.

Có phải họ không? Tôi đã chạy thử nghiệm nhanh: jsperf.com/feft-vs-no-feft/2 và dường như, sự khác biệt đó không nhiều.
Martin Schlagnitweit

25
7,5ns so với 8,8ns. Thêm 1,3 nano giây sẽ thực sự giết chết bạn.
Ian Boyd

5
Với tất cả thời gian tôi dành dụm, tôi đã đưa gia đình đến Thế giới Disney! :-)
Tom

1
Hoàn toàn chính xác. Những người viết các giải pháp "thông minh" có lẽ không bao giờ phải duy trì các mã lập trình viên khác "đá quý"
Avi

1
tại sao không function toggle(i){ return i == 0 ? 1 : 0 }?
Billy Moon

13

Tôi không biết lý do tại sao bạn muốn xây dựng booleans của riêng bạn? Tôi thích các cú pháp sôi nổi, nhưng tại sao không viết mã dễ hiểu?

Đây không phải là ngắn nhất / nhanh nhất, nhưng rõ ràng nhất (và dễ đọc nhất cho mọi người) đang sử dụng trạng thái if / other nổi tiếng:

if (v === 0)
{
  v = 1;
}
else
{
  v = 0;
}

Nếu bạn muốn thực sự rõ ràng, bạn nên sử dụng booleans thay vì số cho việc này. Họ đủ nhanh cho hầu hết các trường hợp. Với booleans, bạn chỉ cần sử dụng cú pháp này, sẽ giành chiến thắng trong thời gian ngắn:

v = !v;

1
Đây thực sự sẽ là câu trả lời ưa thích của tôi; nhưng người điều hành ternary vs if-other là một cuộc chiến thần thánh mà tôi không muốn làm sáng ngòi. Điều đó nói rằng, tôi nghĩ rằng dòng đầu tiên nên được === 0. Với đầu vào mẫu của 7, đầu ra chính xác là 0, nhưng điều này sẽ xuất ra 1.
Ian Boyd

4
Có giá trị để âm thầm sửa một đầu vào như 7 thay vì ném một ngoại lệ nào đó không? Ý tôi là nếu một số mã khác có trong tay số 7 khi nó chỉ mong đợi 0 hoặc 1, trước khi mã của bạn sửa giá trị thì sao?
Chuck van der Linden

12

Một hình thức khác của giải pháp ban đầu của bạn:

v = Number(v == 0);

EDIT: Cảm ơn TehShrike và Guffa đã chỉ ra lỗi trong giải pháp ban đầu của tôi.


4
Toán tử == trả về một boolean (thay vì một số nguyên) trong nhiều hệ thống. Điều này sẽ chỉ hoạt động nếu v được định nghĩa là một số nguyên và ngôn ngữ thật tuyệt vời khi tự động chuyển từ boolean sang số nguyên.
TehShrike

Rất đúng. Tôi đã trả lời câu hỏi trong ngữ cảnh của javascript (cách câu hỏi được gắn thẻ).
Kurt Kaylor

@Kurt Kaylor: Javascript là một trong những hệ thống mà toán tử == trả về boolean, do đó, nó không làm giống như giải pháp ban đầu.
Guffa

@Guffa: Tôi đang lợi dụng thực tế rằng javascript là ngôn ngữ được gõ yếu với chuyển đổi loại ẩn (ví dụ: '00.0000' == 0, 0 == "", false == "", false == 0, 1 == đúng, v.v.) Tôi có thể sử dụng giá trị boolean được trả về giống như cách tôi có thể sử dụng số nguyên có giá trị 0 hoặc 1. Ví dụ: để đánh giá "2 + true" trong bảng điều khiển javascript, bạn sẽ nhận được 3.
Kurt Kaylor

1
@Kurt Kaylor: Điều đó chỉ hoạt động trong các tình huống mà bạn buộc chuyển đổi ngầm. Hãy thử ví dụ 'opacity:'+truevà bạn kết thúc với opacity:truethay vì opacity:1.
Guffa

11

Tôi sẽ làm cho nó rõ ràng hơn.

vnghĩa là gì?

Ví dụ khi v là một số trạng thái. Tạo một trạng thái đối tượng. Trong DDD một đối tượng giá trị.

Thực hiện logic trong đối tượng giá trị này. Sau đó, bạn có thể viết mã của mình theo cách có chức năng hơn, dễ đọc hơn. Chuyển trạng thái có thể được thực hiện bằng cách tạo Trạng thái mới dựa trên trạng thái hiện tại. Câu lệnh if / logic của bạn sau đó được gói gọn trong đối tượng của bạn, cái mà bạn có thể bỏ qua. Một valueObject luôn luôn bất biến, vì vậy nó không có danh tính. Vì vậy, để thay đổi giá trị của nó, bạn phải tạo một cái mới.

Thí dụ:

public class Status
{
    private readonly int _actualValue;
    public Status(int value)
    {
        _actualValue = value;
    }
    public Status(Status status)
    {
        _actualValue = status._actualValue == 0 ? 1 : 0; 
    }

    //some equals method to compare two Status objects
}

var status = new Status(0);

Status = new Status(status);

6
quá kỹ thuật?
alejandro5042

6
+1 để khiến tôi cười
Denshi


10

Điều này bị thiếu:

v = [1, 0][v];

Nó cũng hoạt động như một vòng tròn:

v = [2, 0, 1][v]; // 0 2 1 0 ...
v = [1, 2, 0][v]; // 0 1 2 0 ...
v = [1, 2, 3, 4, 5, 0][v]; // 0 1 2 3 4 5 ...
v = [5, 0, 1, 2, 3, 4][v]; // 0 5 4 3 2 1 0 ...

Hoặc là

v = {0: 1, 1: 0}[v];

Sự quyến rũ của giải pháp cuối cùng, nó cũng hoạt động với tất cả các giá trị khác.

v = {777: 'seven', 'seven': 777}[v];

Đối với trường hợp rất đặc biệt, muốn lấy giá trị (thay đổi) và undefined, mẫu này có thể hữu ích:

v = { undefined: someValue }[v]; // undefined someValue undefined someValue undefined ...

9

Vì đây là JavaScript, chúng tôi có thể sử dụng unary +để chuyển đổi sang int:

v = +!v;

Điều này sẽ logic NOTgiá trị của v(đưa ra truenếu v == 0hoặc falsenếu v == 1). Sau đó, chúng tôi chuyển đổi giá trị boolean trả về thành biểu diễn số nguyên tương ứng của nó.



7

Một lần nữa: v=++v%2

(trong C nó sẽ đơn giản ++v%=2)

ps. Vâng, tôi biết đó là phép gán kép, nhưng đây chỉ là viết lại thô của phương thức C (không hoạt động như vậy, vì toán tử tăng trước JS không trả về giá trị.


3
Phiên bản C của bạn là bất hợp pháp; bạn không thể sửa đổi kết quả của một ++toán tử (nó không phải là giá trị). Đối với v=++v%2, bạn đang sửa đổi vhai lần. Tôi không biết liệu điều đó có được xác định rõ trong JavaScript hay không, nhưng nó không cần thiết. v = (v+1) % 2.
Keith Thompson

Ít nhất là trong c++đó - bởi vì toán tử tăng trước có mức độ ưu tiên cao hơn và sửa đổi biến 'tại chỗ', do đó, nó có thể được sử dụng làm giá trị. Tôi nghĩ rằng việc triển khai JS ++là không thể coi đó là một giá trị: / Và đúng vậy, điều này là dư thừa, nhưng tôi đã cố gắng chỉ ra một phương pháp khác - đã có các giải pháp tốt hơn được đăng lên :)
Adam Jurc:

3
+1. Có thể được viết là v = (v + 1)% 2.
niktrs

7

Nếu bạn được đảm bảo đầu vào của bạn là 1 hoặc 0, thì bạn có thể sử dụng:

v = 2+~v;

7

xác định một mảng {1,0}, đặt v thành v [v], do đó v có giá trị 0 trở thành 1 và ngược lại.


Giải pháp của tôi là chính xác, nếu bạn không thích nó, hãy viết tại sao. Nhận xét của bạn không giúp được ai. Giải pháp của tôi đọc một biến, trái ngược với việc đưa ra quyết định. Điều này đòi hỏi ít CPU hơn.
S ..

5

Một cách sáng tạo khác để làm điều đó, vbằng với bất kỳ giá trị nào, sẽ luôn trả về 0hoặc1

v = !!v^1;

3
hai !!kết quả không có gì trong toán học logic, bạn có thể đặt !!!!vào đó và sẽ giống nhau nhưng dẫn đến 4 thao tác không cần thiết
Alex K

10
@Alex: !!sẽ chuyển sang bool. !!(1) === true!!(0) === false
nickf

1
@nickf: aha, vì vậy tôi đoán v = Boolean(v^1)sẽ có nhiều thông tin hơn, cảm ơn vì đã giải thích - không nghĩ đến việc casting
Alex K

1
@Alex, "toán logic"? Đây là lý do tại sao các nhà toán học là những lập trình viên nghèo. Đừng hiểu lầm tôi; lập trình viên giỏi cũng giỏi hiểu toán. Nhưng điều này không liên quan gì đến toán học logic. Đó là một cấu trúc ngôn ngữ, với bất kỳ biểu thức nào, ít nhất là trong Javascript, !sẽ chuyển nó thành boolean. Thêm một cái khác !sẽ phủ nhận rằng boolean. Việc đúc được ẩn ở đây, và kết quả cuối cùng hoạt động. Không cần -1.
Yanick Rochon

1
Tôi không phải là một nhà toán học. bạn có thể thử điều này và thấy mình jsperf.com/javascript-boolean-test
Alex K

4

Nếu các giá trị có thể có cho v chỉ là 0 và 1, thì với bất kỳ số nguyên x nào, biểu thức: v = Math.pow ((Math.pow (x, v) - x), v); sẽ chuyển đổi giá trị.

Tôi biết đây là một giải pháp xấu và OP đã không tìm kiếm điều này ... nhưng tôi đã suy nghĩ về một giải pháp khác khi tôi ở trong loo: P




1

Nếu chỉ có hai giá trị, như trong trường hợp này (0, 1), tôi tin rằng thật lãng phí khi sử dụng int. Thay vì đi boolean và làm việc theo bit. Tôi biết tôi đang giả định nhưng trong trường hợp chuyển đổi giữa hai trạng thái boolean dường như là lựa chọn lý tưởng.


1

Chà, như chúng ta biết rằng chỉ trong javascript, phép so sánh Boolean cũng sẽ mang lại cho bạn kết quả như mong đợi.

tức v = v == 0là đủ cho điều đó.

Dưới đây là mã cho rằng:

var v = 0;
alert("if v  is 0 output: " + (v == 0));

setTimeout(function() {
  v = 1;
  alert("if v  is 1 Output: " + (v == 0));
}, 1000);

Mã thông báo: https://jsfiddle.net/vikash2402/83zf2zz0/

Hy vọng điều này sẽ giúp bạn :)


Điều đó hoạt động để chuyển đổi một giá trị, nhưng giá trị không chuyển đổi giữa 0 và 1, mà là giữa truefalse. Bạn có thể sử dụng v == 0để xác định giá trị của biến trong một điều kiện, nhưng nếu bạn muốn sử dụng giá trị 0 hoặc 1, bạn sẽ cần sử dụng một cái gì đó như v == 0 ? 0 : 1hoặc Number(v)để có được điều đó. (Ngoài ra, bạn có thể sử dụng v = !v;để chuyển đổi giữa truefalse.)
Guffa

vâng hiểu rồi .. cảm ơn bạn :)
Vikash Pandey

0

v = Số (! v)

Nó sẽ gõ cast giá trị Boolean ngược thành Number, là đầu ra mong muốn.

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.