जावास्क्रिप्ट में कोई तार्किक Xor क्यों नहीं है?


जवाबों:


358

जावास्क्रिप्ट अपने पूर्वजों को C पर वापस लाती है, और C के पास तार्किक XOR ऑपरेटर नहीं है। मुख्यतः क्योंकि यह उपयोगी नहीं है। बिटवाइज़ एक्सओआर बेहद उपयोगी है, लेकिन मेरे सभी वर्षों के प्रोग्रामिंग में मुझे कभी भी तार्किक एक्सओआर की आवश्यकता नहीं थी।

यदि आपके पास दो बूलियन चर हैं, तो आप XOR की नकल कर सकते हैं:

if (a != b)

दो मनमाने ढंग से चर के साथ आप !उन्हें बूलियन मान के लिए इस्तेमाल कर सकते हैं और फिर उसी चाल का उपयोग कर सकते हैं:

if (!a != !b)

हालांकि यह बहुत अस्पष्ट है और निश्चित रूप से एक टिप्पणी के लायक होगा। वास्तव में, आप इस बिंदु पर बिटवॉयर XOR ऑपरेटर का भी उपयोग कर सकते हैं, हालांकि यह मेरे स्वाद के लिए बहुत अधिक चतुर होगा:

if (!a ^ !b)

केवल समस्या !=यह है कि आप ऐसा नहीं कर सकते हैं a ^= b, क्योंकि a !== bसिर्फ सख्त असमानता ऑपरेटर है।
mcpiroman

79

जावास्क्रिप्ट में एक बिटवाइज़र XOR ऑपरेटर है: ^

var nb = 5^9 // = 12

आप इसे बूलियन के साथ उपयोग कर सकते हैं और यह 0 या 1 के रूप में परिणाम देगा (जिसे आप वापस बूलियन में बदल सकते हैं, जैसे result = !!(op1 ^ op2))। लेकिन जैसा कि जॉन ने कहा, यह इसके बराबर है result = (op1 != op2), जो स्पष्ट है।


28
यह समझदार XOR है, तार्किक नहीं XOR
इस्माइल बदावी

66
आप इसे लॉजिकल एक्सोर के रूप में उपयोग कर सकते हैं। true^trueहै 0, और false^trueहै 1.
पिकरस

14
@Pikrass आप इसे बूलियन पर एक तार्किक ऑपरेटर के रूप में उपयोग कर सकते हैं , लेकिन अन्य प्रकारों पर नहीं। ||और &&गैर- बूलियंस पर तार्किक ऑपरेटरों के रूप में इस्तेमाल किया जा सकता है (उदाहरण के लिए एक सत्य मान देता है 5 || 7, "bob" && nullएक गलत मूल्य देता है) लेकिन ^नहीं कर सकता। उदाहरण के लिए, 5 ^ 72 के बराबर है, जो सत्य है।
मार्क अमेरी

10
@Pikrass लेकिन दुख की बात है, (true ^ false) !== trueजो इसे उन पुस्तकालयों से परेशान कर रहा है जिनके लिए वास्तविक
बूलियंस की

2
@Pikrass आपको बूलियन पर एक तार्किक ऑपरेटर के रूप में इसका उपयोग कभी नहीं करना चाहिए क्योंकि कार्यान्वयन ओएस पर निर्भर है। मैं a ^= trueबूलियन्स को टॉगल करने के लिए किसी तरह का उपयोग कर रहा था और यह कुछ मशीनों जैसे फोन पर विफल रहता है।
मसाडो

30

जावास्क्रिप्ट में कोई वास्तविक तार्किक बूलियन ऑपरेटर नहीं हैं (हालांकि !काफी करीब आता है)। एक तार्किक ऑपरेटर केवल trueया falseऑपरेंड के रूप में ले जाएगा और केवल trueया वापस आ जाएगा false

जावास्क्रिप्ट में &&और ||सभी प्रकार के ऑपरेंड लें और सभी प्रकार के मज़ेदार परिणाम (जो भी आप उन्हें खिलाते हैं) वापस करें।

साथ ही एक तार्किक ऑपरेटर को हमेशा दोनों ऑपरेंड के मूल्यों को ध्यान में रखना चाहिए।

जावास्क्रिप्ट में &&और ||एक आलसी शॉर्टकट ले लो और कुछ मामलों में दूसरे ऑपरेंड का मूल्यांकन न करें और इस तरह इसके दुष्प्रभावों की उपेक्षा करें। यह व्यवहार एक तार्किक एक्सोर के साथ फिर से बनाना असंभव है।


a() && b()a()यदि यह गलत है तो परिणाम का मूल्यांकन करता है और लौटाता है। अन्यथा यह मूल्यांकन करता है b()और परिणाम देता है। इसलिए लौटा परिणाम सत्य है यदि दोनों परिणाम सत्य हैं, और मिथ्या है।

a() || b()a()सत्य होने पर परिणाम का मूल्यांकन करता है और वापस करता है। अन्यथा यह मूल्यांकन करता है b()और परिणाम देता है। इसलिए लौटा हुआ परिणाम मिथ्या है अगर दोनों परिणाम गलत हैं, और सत्य अन्यथा।

इसलिए सामान्य विचार यह है कि पहले बाएं ऑपरेंड का मूल्यांकन किया जाए। आवश्यक होने पर ही सही संचालन का मूल्यांकन किया जाता है। और अंतिम मूल्य परिणाम है। यह परिणाम कुछ भी हो सकता है। ऑब्जेक्ट्स, नंबर, स्ट्रिंग्स .. जो भी हो!

इससे चीजों को लिखना संभव हो जाता है

image = image || new Image(); // default to a new Image

या

src = image && image.src; // only read out src if we have an image

लेकिन इस परिणाम के सत्य मूल्य का उपयोग यह तय करने के लिए भी किया जा सकता है कि क्या "वास्तविक" तार्किक ऑपरेटर सही या गलत लौटा होगा।

इससे चीजों को लिखना संभव हो जाता है

if (typeof image.hasAttribute === 'function' && image.hasAttribute('src')) {

या

if (image.hasAttribute('alt') || image.hasAttribute('title')) {

लेकिन एक "तार्किक" xor ऑपरेटर ( ^^) को हमेशा दोनों ऑपरेंड का मूल्यांकन करना होगा। यह इसे अन्य "तार्किक" ऑपरेटरों के लिए अलग बनाता है जो आवश्यक होने पर ही दूसरे ऑपरेंड का मूल्यांकन करते हैं। मुझे लगता है यही कारण है कि भ्रम से बचने के लिए, जावास्क्रिप्ट में कोई "तार्किक" xor नहीं है।


तो क्या होगा यदि दोनों ऑपरेंड गलत हैं? दोनों को लौटाया जा सकता था। लेकिन केवल एक ही लौटाया जा सकता है। कौनसा? पहले वाला? या दूसरा वाला? मेरा अंतर्ज्ञान मुझे पहले वापस करने के लिए कहता है लेकिन आमतौर पर "तार्किक" ऑपरेटर बाएं से दाएं का मूल्यांकन करते हैं और अंतिम मूल्यांकन किए गए मूल्य को वापस करते हैं। या हो सकता है कि एक सरणी जिसमें दोनों मान हों?

और यदि एक ऑपरेंड सत्य है और दूसरा ऑपरेंड झूठा है, तो एक एक्सोर को सच्चाई को वापस करना चाहिए। या हो सकता है कि एक सरणी जिसमें सत्य एक है, उसे पिछले मामले के साथ संगत करने के लिए?

और अंत में, यदि दोनों ऑपरेंड सत्य हैं तो क्या होना चाहिए? आप कुछ झूठा उम्मीद करेंगे। लेकिन कोई मिथ्या परिणाम नहीं हैं। इसलिए ऑपरेशन को कुछ भी वापस नहीं करना चाहिए। तो शायद undefinedया .. एक खाली सरणी? लेकिन एक खाली सरणी अभी भी सत्य है।

ऐरे एप्रोच लेते हुए आप जैसे हालात खत्म हो जाएंगे if ((a ^^ b).length !== 1) {। बहुत ज्यादा उलझन।


XOR / ^ ^ किसी भी भाषा में हमेशा दोनों ऑपरेंड का मूल्यांकन करना होगा क्योंकि यह हमेशा दोनों पर निर्भर है। AND और / & के लिए भी यही होता है, क्योंकि सभी ऑपरेशंस का सत्य होना चाहिए (JS में सत्यता) रिटर्न पास। अपवाद है OR / || चूँकि यह केवल तब तक ऑपरेंड का मूल्यांकन करना चाहिए जब तक कि यह एक सत्य मूल्य नहीं पाता है। यदि OR सूची में पहला ऑपरेंड सत्य है, तो दूसरों का कोई भी मूल्यांकन नहीं किया जाएगा।
पर्सी

आप एक अच्छी बात करते हैं, हालाँकि, JS में XOR को AND और OR द्वारा निर्धारित कन्वेंशन को तोड़ना होगा। यह वास्तव में दो ऑपरेंड में से एक के बजाय एक उचित बूलियन मूल्य वापस करना होगा। और कुछ भी भ्रम / जटिलता पैदा कर सकता है।
पर्सी

9
@Percy और / && दूसरे ऑपरेंड का मूल्यांकन नहीं करता है यदि पहला गलत है। यह केवल ऑपरेशंस का मूल्यांकन करता है जब तक कि यह एक मिथ्या मूल्य नहीं पाता है।
रॉबर्ट

@ डीडीएस उत्तर को सुधारने के लिए धन्यवाद। मैं हैरान हूं कि मैंने इसे खुद क्यों नहीं नोटिस किया। हो सकता है कि यह कुछ हद तक पर्सी की उलझन को समझाए।
रॉबर्ट

मेरा संपादन अस्वीकार कर दिया गया था, जिसके बाद @matts ने इसे ठीक उसी तरह संपादित किया, जिस तरह से मैंने इसे ठीक किया, इसलिए मैंने अपने (औसतन) 2 अंक गंवा दिए। 3 लोगों ने इसे अस्वीकार कर दिया है और मुझे लगा कि वे अपने मापदंड के रूप में इसका उपयोग कर रहे हैं। Thx मैट।
DDS

16

दो बूलियन का XOR बस अलग है, इसलिए वे अलग हैं:

Boolean(a) !== Boolean(b)

12

मानों को बूलियन रूप में परिवर्तित करें और फिर बिटवाइज़ XOR लें। यह गैर-बूलियन मूल्यों के साथ-साथ मदद करेगा।

Boolean(a) ^ Boolean(b)

10

बूलियन को गुप्त और फिर एक्सोर जैसे प्रदर्शन करें -

!!a ^ !!b

1
ध्यान दें कि !!a ^ !!bइसके बराबर है !a ^ !b। तर्क दिया जा सकता है जो पढ़ने में आसान है।
tschwab

9

वहाँ है ... की तरह:

if( foo ? !bar : bar ) {
  ...
}

या पढ़ने में आसान:

if( ( foo && !bar ) || ( !foo && bar ) ) {
  ...
}

क्यों? पता नहीं।

क्योंकि जावास्क्रिप्ट डेवलपर्स ने सोचा कि यह अनावश्यक होगा क्योंकि इसे अन्य, पहले से लागू, तार्किक ऑपरेटरों द्वारा व्यक्त किया जा सकता है।

आप अच्छी तरह से सिर्फ नंद के साथ गन कर सकते हैं और इसे thats, आप उस से हर दूसरे संभव तार्किक संचालन को प्रभावित कर सकते हैं।

मुझे व्यक्तिगत रूप से लगता है कि इसके ऐतिहासिक कारण हैं जो c- आधारित वाक्यविन्यास भाषाओं से चलते हैं, जहाँ मेरा ज्ञान xor मौजूद नहीं है या कम से कम बेहद असामान्य है।


हाँ, जावास्क्रिप्ट में टर्नरी ऑप्स हैं।
mwilcox

C और Java दोनों में ^ (caret) वर्ण का उपयोग कर XOR है।
वेलाडिस

7

हां, बस निम्नलिखित करें। यह मानते हुए कि आप बूलियन्स ए और बी के साथ काम कर रहे हैं, तो निम्नलिखित का उपयोग करके ए XOR बी मूल्य की गणना जावास्क्रिप्ट में की जा सकती है

var xor1 = !(a === b);

पिछली पंक्ति भी निम्न के बराबर है

var xor2 = (!a !== !b);

व्यक्तिगत रूप से, मैं xor1 को पसंद करता हूं क्योंकि मुझे कम वर्ण टाइप करने हैं। मेरा मानना ​​है कि xor1 भी तेज है। यह सिर्फ दो गणना कर रहा है। xor2 तीन गणना कर रहा है।

दृश्य स्पष्टीकरण ... तालिका बोला पढ़ें (जहां 0 झूठ के लिए खड़ा है और 1 सच के लिए खड़ा है) और 3 और 5 वें कॉलम की तुलना करें।

! (ए === बी):

| A | B | A XOR B | A === B | !(A === B) |
------------------------------------------
| 0 | 0 |    0    |    1    |      0     |
| 0 | 1 |    1    |    0    |      1     |
| 1 | 0 |    1    |    0    |      1     |
| 1 | 1 |    0    |    1    |      0     |
------------------------------------------

का आनंद लें।


6
var xor1 = !(a === b);के रूप में ही हैvar xor1 = a !== b;
daniel1426

यह उत्तर सभी डेटा प्रकारों (जैसे प्रेमचंद्र के उत्तर) के लिए काम नहीं करेगा। जैसे !(2 === 3)है true, लेकिन सत्य हैं 2और ऐसा होना भी चाहिए । 32 XOR 3false
Mariano Desanze

2
यदि आपने मेरे संदेश को अधिक ध्यान से पढ़ा था, तो आपने देखा होगा कि मैंने लिखा है कि "आप ए और बी के साथ काम कर रहे हैं ..."।
asiby

5

चेक आउट:

आप इसे इस तरह से नकल कर सकते हैं:

if( ( foo && !bar ) || ( !foo && bar ) ) {
  ...
}

3
अरे, अगर वे जावास्क्रिप्ट में एक तार्किक XOR ऑपरेटर जोड़ते हैं तो यह कोड उदाहरण को बहुत क्लीनर बना देगा।
डेनियल आयटेकिन

4

कैसे परिणाम बदलने के बारे में पूर्णांक एक को bool डबल निषेध के साथ? इतना सुंदर नहीं है, लेकिन वास्तव में कॉम्पैक्ट है।

var state1 = false,
    state2 = true;
    
var A = state1 ^ state2;     // will become 1
var B = !!(state1 ^ state2); // will become true
console.log(A);
console.log(B);


यह विफल हो जाएगा अगर ऑपरेंड पहले से ही बूलियन नहीं हैं। बहुत बेहतर विचार हैB = ((!state1)!==(!state2))
Doin

यह सच है, लेकिन आप हमेशा उन्हें डालने के लिए ऑपरेंड को नकार सकते हैं, जैसे कि यदि आप प्रकारों के बारे में सुनिश्चित नहीं हैं: तो B =!!(!state1 ^ !state2); भी, इतने सारे कोष्ठक क्यों? B = !state1 !== !state2; या आप नकार को भी छोड़ सकते हैं:B = state1 !== state2;
लाजोस मेस्सरोस

कोष्ठक स्पष्टता के लिए हैं, और इसलिए भी मुझे कोड लिखते समय ऑपरेटर पूर्वता पर डॉक्स की जांच करने की आवश्यकता नहीं है! ;-) आपकी पिछली अभिव्यक्ति मेरी पिछली शिकायत से ग्रस्त है: यह विफल हो जाता है अगर ऑपरेंड बूलियन नहीं हैं। लेकिन अगर आपको यकीन है कि वे हैं, तो यह निश्चित रूप से सबसे सरल और सबसे तेज़ "तार्किक एक्सोर" अभिव्यक्ति है।
चल रहा

यदि अंतिम अभिव्यक्ति से आपका मतलब है state1 !== state2, तो आपको वहां कोई कास्टिंग करने की आवश्यकता नहीं है, क्योंकि !==एक तार्किक ऑपरेटर है, एक बिटवाइज़ नहीं। 12 !== 4सच है सच 'xy' !== trueभी है। यदि आप !=इसके बजाय उपयोग करते हैं !==, तो आपको कास्टिंग करना होगा।
लाजोस मेस्सरोस

1
दोनों का परिणाम है !==और !=हमेशा बूलियन है ... निश्चित नहीं है कि आप जो अंतर बना रहे हैं वह माना जाता है, यह समस्या नहीं है। समस्या यह है कि XOR ऑपरेटर जो हम चाहते हैं वह वास्तव में अभिव्यक्ति है (Boolean(state1) !== Boolean(state2))। बूलियन्स के लिए, "xy", 12, 4 और true सभी सत्य मूल्य हैं, और इन्हें परिवर्तित करना चाहिए true। ऐसा ("xy" XOR true)होना चाहिए false, लेकिन ("xy" !== true)इसके बजाय true, जैसा कि आप बताते हैं। तो !==या !=(दोनों) "तार्किक XOR" के बराबर हैं यदि और केवल यदि आप आवेदन करने से पहले अपने तर्क को बूलियंस में बदल देते हैं ।
चल रहा

2

ऊपर दिए गए xor फ़ंक्शन में यह SIMILAR का परिणाम देगा क्योंकि तार्किक xor बिल्कुल तार्किक xor नहीं है, इसका अर्थ है कि यह "समान मूल्यों के लिए असत्य" और "अलग-अलग मूल्यों के लिए सत्य" के रूप में विचार में मिलान के साथ परिणाम देगा ।

यह XOR समारोह वास्तविक XOR या तार्किक ऑपरेटर के रूप में काम करेंगे , के लिए गुजर मान हैं यह सही या गलत के अनुसार परिणाम होगा साधन truthy या falsy । अपनी आवश्यकताओं के अनुसार उपयोग करें

function xor(x,y){return true==(!!x!==!!y);}

function xnor(x,y){return !xor(x,y);}

"xnor" "===" के समान है।
daniel1426

@ daniel1426 काफी नहीं। यह वैसा ही है (!!x) === (!!y)। अंतर बूलियन के लिए एक डाली है। '' === 0असत्य है, जबकि xnor('', 0)सत्य है।
tschwab

2

टाइपस्क्रिप्ट में (संख्यात्मक मान में परिवर्तन):

value : number = (+false ^ +true)

इसलिए:

value : boolean = (+false ^ +true) == 1

@ सामान्य जावास्क्रिप्ट में शेफ़र, बूलियन के !!(false ^ true)साथ ठीक काम करता है। टाइपस्क्रिप्ट में, + इसे वैध बनाने के लिए आवश्यक है !!(+false ^ +true)
PFG

1

cond1 xor cond2के बराबर है cond1 + cond 2 == 1:

यहाँ सबूत है:

let ops = [[false, false],[false, true], [true, false], [true, true]];

function xor(cond1, cond2){
  return cond1 + cond2 == 1;
}

for(op of ops){
  console.log(`${op[0]} xor ${op[1]} is ${xor(op[0], op[1])}`)
}


0

कारण कोई तार्किक XOR (^ ^) नहीं है, क्योंकि && और || यह कोई आलसी-तर्क लाभ नहीं देता है। यह दाएं और बाएं दोनों अभिव्यक्तियों की स्थिति का मूल्यांकन करना है।


0

यहां एक वैकल्पिक समाधान है जो 2+ चर के साथ काम करता है और बोनस के रूप में गिनती प्रदान करता है।

यहाँ किसी भी सत्य / गलत मूल्यों के लिए तार्किक XOR का अनुकरण करने के लिए एक अधिक सामान्य समाधान है, जैसे कि यदि आप मानक में ऑपरेटर हैं तो आइए जानें:

const v1 = true;
const v2 = -1; // truthy (warning, as always)
const v3 = ""; // falsy
const v4 = 783; // truthy
const v5 = false;

if( ( !!v1 + !!v2 + !!v3 + !!v4 + !!v5 ) === 1 )
  document.write( `[ ${v1} XOR ${v2} XOR "${v3}" XOR ${v4} XOR ${v5} ] is TRUE!` );
else
  document.write( `[ ${v1} XOR ${v2} XOR "${v3}" XOR ${v4} XOR ${v5} ] is FALSE!` );

मुझे यह पसंद है, इसका कारण यह है कि यह भी जवाब देता है "इनमें से कितने चर सत्य हैं?", इसलिए मैं आमतौर पर उस परिणाम को प्री-स्टोर करता हूं।

और उन लोगों के लिए जो सख्त बूलियन-ट्रू एक्सर चेक व्यवहार चाहते हैं, बस:

if( ( ( v1===true ) + ( v2===true ) + ( v3===true ) + ( v4===true ) + ( v5===true ) ) === 1 )
  // etc.

यदि आप गिनती के बारे में परवाह नहीं करते हैं, या यदि आप इष्टतम प्रदर्शन के बारे में परवाह करते हैं: तो बस सचाई / झूठे समाधान के लिए बूलियन के लिए मजबूर मूल्यों पर बिटवाइर एक्सर का उपयोग करें:

if( !!v1 ^ !!v2 ^ !!v3 ^ !!v4 ^ !!v5 )
  // etc.

0

अरे मुझे यह समाधान मिला, बनाने के लिए और जावास्क्रिप्ट और टाइपस्क्रिप्ट पर XOR।

if( +!!a ^ +!!b )
{
  //This happens only when a is true and b is false or a is false and b is true.
}
else
{
  //This happens only when a is true and b is true or a is false and b is false
}

-2

इस छोटे और आसान को समझने की कोशिश करो

function xor(x,y){return true==(x!==y);}

function xnor(x,y){return !xor(x,y);}

यह किसी भी डेटा प्रकार के लिए काम करेगा


3
यह सभी डेटा प्रकारों के लिए काम नहीं करता है। एक तार्किक प्रकार के जबरदस्त ऑपरेटर के साथ, मुझे उम्मीद है कि "फू" xor "बार" गलत होगा, क्योंकि दोनों सत्य हैं। यह वर्तमान में आपके फ़ंक्शन के मामले में नहीं है। आम तौर पर, करना true == somebooleanआवश्यक नहीं है, इसलिए वास्तव में, आपने जो किया है वह एक फ़ंक्शन में सख्त नहीं के बराबर लपेट रहा है।
गीज्स जूल

हाय GiJs, मैं आपके तर्क से सहमत हूँ, "फू" और "बार" सत्य मान हैं। लेकिन मैं फ़ंक्शन को ध्यान में रखते हुए लिखता हूं कि यह समान आउटपुट का परिणाम देगा क्योंकि xor करता है (समान-बराबर मान परिणाम, समान मान परिणाम गलत) केवल सत्य / मिथ्या मूल्य के लिए नहीं। और मैंने ऐसे परिदृश्य में अधिक उपयोग पाया। लेकिन मैं नीचे एक और उत्तर में सच्चा तार्किक xor लिख रहा हूं।
प्रेमचंद्र सिंह
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.