Frage

Ich versuche, XOR in JavaScript auf folgende Weise zu implementieren:

   // XOR validation
   if ((isEmptyString(firstStr) && !isEmptyString(secondStr)) ||
    (!isEmptyString(firstStr) && isEmptyString(secondStr))
   {
    alert(SOME_VALIDATION_MSG);
    return;
   }

Gibt es einen besseren Weg, dies in JavaScript zu tun?

Vielen Dank.

War es hilfreich?

Lösung

Ich tue vor, dass Sie nach einem logischen XOR suchen, da JavaScript bereits eine bitgewise (^) hat :)

Normalerweise verwende ich einen einfachen ternären Operator (eine der seltenen Zeiten, in denen ich eines benutze):

if ((isEmptyString(firstStr) ? !isEmptyString(secondStr) 
                             : isEmptyString(secondStr))) {
alert(SOME_VALIDATION_MSG);
    return;
}

Bearbeiten:

Arbeiten am @jeff Fleischbällchen Yang Lösung

if ((!isEmptyString(firstStr) ^ !isEmptyString(secondStr))) {
  alert(SOME_VALIDATION_MSG);
  return;
}

Sie negieren die Werte, um sie in Booleschen zu transformieren, und wenden dann den bitweisen XOR -Operator an. Vielleicht ist es nicht so aufrechterhalten wie die erste Lösung (oder vielleicht bin ich an die erste gewöhnt)

Andere Tipps

Wie andere betont haben, ist logical XOR für Booleschen das gleiche wie nicht gleich, sodass Sie dies tun können:


  // XOR validation
  if( isEmptyString(firstStr) != isEmptyString(secondStr) )
    {
      alert(SOME_VALIDATION_MSG);
      return;
    }

Sie machen eine XOR von booleschen Werten, die leicht in ein bitweise XOR zu modellieren sind (was JavaScript hat):

var a = isEmptyString(firstStr) ? 1 : 0;
var b = isEmptyString(secondStr) ? 1 : 0;

if(a ^ b) { ... }

http://www.howtocreate.co.uk/xor.html

Sie können den Bitwise XOR -Operator verwenden (^) direkt:

if (isEmptyString(firstStr) ^ isEmptyString(secondStr)) {
  // ...
}

Es funktioniert für Ihr Beispiel seit dem Booleschen true und false Werte werden in konvertiert in 1 und 0 Weil die bitweisen Betreiber mit 32-Bit-Ganzzahlen arbeiten.

Dieser Ausdruck wird auch zurückkehren 0 oder 1, und dieser Wert wird von der wieder auf Booleschen if Aussage.

Sie sollten sich des Typ -Zwangs bewusst sein, der mit dem obigen Ansatz auftritt. Wenn Sie nach einer guten Leistung suchen, würde ich Ihnen nicht empfehlen, mit den bitweisen Operatoren zusammenzuarbeiten Operatoren:

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


if (xor(isEmptyString(firstStr), isEmptyString(secondStr))) {
  // ...
}

Einfachere Methode:

if ((x+y) % 2) {
    //statement
}

Angenommen, beide Variablen sind echte Boolesche, das heißt, 1 oder 0.

  • Wenn x === y Sie erhalten eine gleichmäßige Zahl, also wird Xor sein 0.
  • Und wenn x !== y Dann bekommst du eine ungerade Nummer, also wird Xor sein 1 :)

Eine zweite Option, wenn Sie das bemerken x != y bewertet als XOR, dann müssen Sie nur noch tun, ist

if (x != y) {
    //statement
}

Das wird nur wieder als XOR bewerten. (Ich mag das viel besser)

Natürlich wäre eine nette Idee, dies in eine Funktion zu implementieren, aber es ist nur Ihre Wahl.

Hoffe eine der beiden Methoden hilft jemandem! Ich markiere diese Antwort als Community -Wiki, damit sie verbessert werden kann.

Kasse Dies Erläuterung verschiedener Implementierungen von XOR in JavaScript.

Nur um ein paar von ihnen hier zusammenzufassen:

if( ( isEmptyString(firstStr) || isEmptyString(secondStr)) && !( isEmptyString(firstStr) && isEmptyString(secondStr)) ) {
   alert(SOME_VALIDATION_MSG); 
   return; 
}

ODER

if( isEmptyString(firstStr)? !isEmptyString(secondStr): isEmptyString(secondStr)) {
   alert(SOME_VALIDATION_MSG); 
   return;
}

ODER

if( (isEmptyString(firstStr) ? 1 : 0 ) ^ (isEmptyString(secondStr) ? 1 : 0 ) ) {
   alert(SOME_VALIDATION_MSG); 
   return;
}

ODER

if( !isEmptyString(firstStr)!= !isEmptyString(secondStr)) {
   alert(SOME_VALIDATION_MSG); 
   return;
}

Zitieren von Dies Artikel:

Leider hat JavaScript keinen logischen XOR -Operator.

Sie können das Verhalten des XOR -Operators mit so etwas "emulieren":

if( !foo != !bar ) {
  ...
}

Der verknüpfte Artikel erörtert einige alternative Ansätze.

XOR bedeutet nur "Unterscheiden diese beiden booleschen Werte?". Deswegen:

if (!!isEmptyString(firstStr) != !!isEmptyString(secondStr)) {
    // ...
}

Das !!s sollen nur garantieren, dass die != Der Bediener vergleicht zwei echte boolesche Werte, da er denkbar ist isEmptyString() Gibt etwas anderes zurück (wie null für false oder die Zeichenfolge selbst für wahr).

Angenommen, Sie suchen nach dem Booleschen XOR, hier eine einfache Implementierung.

function xor(expr1, expr2){
    return ((expr1 || expr2) && !(expr1 && expr2));
}

Das obige leitet sich aus der Definition einer "exklusiven Disjunktion" ab {entweder eins, aber nicht beide}.

Da die booleschen Werte true und false werden in konvertiert zu 1 und 0 Bei der Verwendung von Bitwise-Operatoren auf ihnen den Bitgewise-Xor ^ Kann als logisches XOR sowie Bitwiseone doppelt so hoch sein, solange Ihre Werte boolesche Werte sind (JavaScripts "wahrheitsgemäße" Werte funktionieren nicht). Dies ist leicht mit der Negation zu erreichen ! Operator.

a XOR b ist logisch äquivalent der folgenden (kurzen) Liste von Ausdrücken:

!a ^ !b;
!a != !b;

Es sind viele andere Formen möglich - wie z. !a ? !!b : !b - Aber diese beiden Muster haben den Vorteil, nur zu bewerten a und b Einmal jedes (und wird auch nicht "Kurzschluss" sein, wenn a ist falsch und somit nicht bewertet b), während Formen mit ternärischen Formen ?:, ODER ||, oder und && Die Betreiber werden entweder doppelt bewerten oder Kurzschluss.

Die Negation ! Die Betreiber in beiden Aussagen sind aus ein paar Gründen wichtig, um alle "wahrheitlichen" Werte in boolesche Werte ("" -> False, 12 -True usw.) umzuwandeln, so dass der Bitgewise -Operator Werte hat, mit denen er arbeiten kann. Also die Ungleichheit != Der Operator vergleicht den Wahrheitswert jedes Ausdrucks nur (a != b würde nicht richtig funktionieren, wenn a oder b waren nicht gleiche, nicht leere Zeichenfolgen usw.), und so dass jede Bewertung ein boolescher Wertergebnis anstelle des ersten "wahrheitsgemäßen" Werts zurückgibt.

Sie können diese Formen weiter erweitern, indem Sie doppelte Negationen (oder die Ausnahme, Hinzufügen !!a ^ !!b, was Xor noch äquivalent ist), aber seien Sie vorsichtig, wenn Sie nur einen Teil des Ausdrucks negieren. Diese Formen scheinen auf den ersten Blick "zu arbeiten", wenn Sie in Bezug auf die Verteilung in arithmatisch denken (wo 2(a + b) == 2a + 2b, usw.), aber tatsächlich verschiedene Wahrheitstabellen von xor (Diese erzeugen ähnliche Ergebnisse wie logisch nxor):

!( a ^ b )
!( !!a ^ !!b )
!!a == !!b

Die allgemeine Form für XOR könnte also die Funktion sein (Wahrheitstabelle Geige):

function xor( a, b ) { return !a ^ !b; }

Und Ihr spezifisches Beispiel wäre dann:

if ( xor( isEmptyString( firstStr ), isEmptyString( secondStr ) ) ) { ... }

Oder wenn isEmptyString Gibt nur Boolesche Werte zurück und Sie wollen keinen General xor Funktion, einfach:

if ( isEmptyString( firstStr ) ^ isEmptyString( secondStr ) ) { ... }

JavaScript hat keinen logischen XOR -Operator, sodass Ihr Konstrukt plausibel erscheint. Wären es Zahlen gewesen, hätten Sie dann einen bitweisen XOR -Operator verwenden können.

Prost

Hier ist ein XOR, das von zwei bis zu vielen Argumenten gerecht werden kann

function XOR() {
    for (var i = 1; i < arguments.length; i++) 
        if ( arguments[0] != arguments[i] ) 
            return false; 
    return true; 
}

Beispiel der Verwendung:

if ( XOR( isEmptyString(firstStr), isEmptyString(secondStr) ) ) {
    alert(SOME_VALIDATION_MSG);
    return;
}

Ich hoffe, dies wird das kürzeste und sauberste sein

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

Dies funktioniert für jeden Typ

Hier ist eine XOR -Funktion, die eine variable Anzahl von Argumenten (einschließlich zwei) nimmt. Die Argumente müssen nur wahr oder falsy sein, nicht true oder false.

function xor() {
    for (var i=arguments.length-1, trueCount=0; i>=0; --i)
        if (arguments[i])
            ++trueCount;
    return trueCount & 1;
}

Auf Chrome auf meinem 2007er MacBook wird in 14 NS für drei Argumente ausgeführt. Seltsamerweise nimmt diese etwas andere Version 2935 NS für drei Argumente an:

function xorSlow() {
    for (var i=arguments.length-1, result=false; i>=0; --i)
        if (arguments[i])
            result ^= true;
    return result;
}

Versuche dies: function xor(x,y) var result = x || y if (x === y) { result = false } return result }

Es gibt ein paar Methoden, aber die ternäre Methode (a?! B: b) scheint am besten zu funktionieren. Außerdem scheint das Einstellen von boolean.prototype.xor eine Option zu sein, wenn Sie die Dinge häufig xor benötigen.

http://jsperf.com/xor-implementations

Sie könnten das tun:

Math.abs( isEmptyString(firstStr) - isEmptyString(secondStr) )

Das Ergebnis davon ist das Ergebnis einer XOR -Operation.

@George, ich mag Ihre Funktion für ihre Fähigkeit, mehr als 2 Operanden zu erstellen. Ich habe eine leichte Verbesserung, damit es schneller zurückkehrt:

function xor() {
    for (var i=arguments.length-1, trueCount=0; i>=0; --i)
        if (arguments[i]) {
            if (trueCount)
                return false
            ++trueCount;
        }
    return trueCount & 1;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top