web-dev-qa-db-fra.com

Est-il possible de mettre en œuvre XOR en javascript

J'essaie d'implémenter XOR en javascript de la manière suivante:

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

Y a-t-il une meilleure façon de faire cela en javascript?

Merci.

41
amoran

Je prétends que vous recherchez un XOR logique, car javascript en a déjà un de bitwise (^) :)

J'utilise généralement un simple opérateur ternaire (une des rares fois où j'en utilise un):

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

Modifier:

travaille sur la @Jeff Meatball Yang solution

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

vous niez les valeurs pour les transformer en booléens, puis appliquez l'opérateur xor au niveau du bit. Peut-être que ce n'est pas aussi facile à maintenir que la première solution (ou peut-être que je suis trop habitué à la première)

34
Eineki

Comme d'autres l'ont déjà souligné, la logique XOR est identique à celle qui n'est pas identique pour les booléens. Vous pouvez donc procéder ainsi:


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

Vous faites un XOR de valeurs booléennes facile à modéliser en un bitwise XOR (que Javascript a):

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

if(a ^ b) { ... }

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

11
Jeff Meatball Yang

Vous pouvez utiliser l'opérateur XOR au niveau du bit (^) directement:

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

Cela fonctionnera pour votre exemple car les valeurs booléennes true et false sont converties en 1 et 0 car les opérateurs au niveau du bit fonctionnent avec des entiers 32 bits.

Cette expression renverra aussi soit 0, soit 1, et cette valeur sera contrainte de revenir à Boolean par l'instruction if.

Vous devez être conscient de la coercition de types qui se produit avec l'approche ci-dessus. Si vous recherchez de bonnes performances, je ne vous recommanderais pas de travailler avec les opérateurs au niveau des bits, vous pouvez également créer une fonction simple pour le faire en utilisant uniquement la logique booléenne les opérateurs:

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


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

Plus facile une méthode:

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

en supposant bien sûr que les deux variables sont de vrais booléens, c'est-à-dire 1 ou 0.

  • Si x === y vous obtiendrez un nombre pair, donc XOR sera 0.
  • Et si x !== y, vous obtiendrez un nombre impair, donc XOR sera 1 :)

Une deuxième option, si vous remarquez que x != y est évalué comme un XOR, vous devez simplement:

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

Ce qui va juste évaluer, encore une fois, en tant que XOR. (J'aime beaucoup mieux ça)

Bien sûr, une bonne idée serait d'implémenter cela dans une fonction, mais c'est votre choix.

J'espère que l'une des deux méthodes aidera quelqu'un! Je marque cette réponse en tant que wiki de communauté, afin qu'elle puisse être améliorée.

7
Nico

Checkout this explication des différentes implémentations de XOR en javascript.

Juste pour résumer quelques-uns ici:

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

OR

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

OR

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

OR

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

Citant de this article:

Malheureusement, JavaScript n’a pas d’opérateur logique XOR.

Vous pouvez "émuler" le comportement de l'opérateur XOR avec quelque chose comme:

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

L'article lié traite de quelques approches alternatives.

5
Roberto Aloi

Etant donné que les valeurs booléennes true et false sont converties en 1 et 0 respectivement lors de l’utilisation d’opérateurs au niveau du bit, le bitwise-XOR ^ peut jouer le rôle double en tant que XOR logique _ ainsi que bitwiseone, tant que vos valeurs sont des valeurs booléennes (les valeurs "vérité" de Javascript ne fonctionneront pas). Ceci est facile à réaliser avec l’opérateur négation !.

a XOR b est logiquement équivalent à la liste (courte) d'expressions suivante:

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

Il y a beaucoup d'autres formes possibles - telles que !a ? !!b : !b - mais ces deux modèles ont l'avantage de n'évaluer que a et b une fois chacun (et ne "court-circuiteront" pas trop si a est faux et n'évaluera donc pas b), tandis que les formes L'utilisation d'opérateurs ternaires ?:, OR || et AND && permet une double évaluation ou un court-circuit.

Les opérateurs de négation ! dans les deux instructions sont importants à inclure pour plusieurs raisons: il convertit toutes les valeurs "vérités" en valeurs booléennes ("" -> false, 12 -> true, etc.), de sorte que l'opérateur au niveau du bit ait des valeurs qu'il peut work with, donc l'opérateur != d'inégalité ne compare que la valeur de vérité de chaque expression (a != b ne fonctionnerait pas correctement si a ou b étaient des chaînes non égales, non vides, etc.) et que chaque évaluation renvoyait un résultat booléen au lieu de la première valeur "vérité".

Vous pouvez continuer à développer ces formulaires en ajoutant des doubles négations (ou l'exception, !!a ^ !!b, qui est toujours équivalente à XOR), mais soyez prudent lorsque vous niez qu'une partie de l'expression. Ces formes peuvent sembler à première vue "fonctionner" si vous pensez en termes de distribution arithmatique (où 2(a + b) == 2a + 2b, etc.), mais produisent en fait des tables de vérité différentes de XOR ( elles produisent résultats similaires à logical NXOR ):

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

La forme générale de XOR pourrait alors être la fonction ( violon de table de vérité ):

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

Et votre exemple spécifique serait alors:

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

Ou si isEmptyString ne renvoie que des valeurs booléennes et que vous ne voulez pas de fonction générale xor, simplement:

if ( isEmptyString( firstStr ) ^ isEmptyString( secondStr ) ) { ... }
2
Brian North

XOR signifie simplement "ces deux valeurs booléennes sont-elles différentes?". Donc:

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

Les !!s servent uniquement à garantir que l'opérateur != compare deux valeurs booléennes authentiques, car il est concevable que isEmptyString() renvoie autre chose (comme null pour false ou la chaîne elle-même pour true).

2
Sean

En supposant que vous cherchiez le BOOLEAN XOR, voici une implémentation simple.

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

Ce qui précède dérive de la définition d’une "disjonction exclusive" {l’un ou l’autre, mais pas les deux}.

2
Butshuti Hakiza

Javascript n'a pas d'opérateur logique XOR, votre construction semble donc plausible. Si cela avait été un nombre, vous auriez pu utiliser ^ c.-à-d. Bitwise XOR.

à votre santé

1
Arnkrishn

voici un XOR pouvant gérer de deux à plusieurs arguments

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

Exemple d'utilisation:

if ( XOR( isEmptyString(firstStr), isEmptyString(secondStr) ) ) {
    alert(SOME_VALIDATION_MSG);
    return;
}
1
some young guy

J'espère que ce sera le plus court et le plus propre

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

Cela fonctionnera pour tout type

1

@george, j'aime votre fonction car elle est capable de prendre plus de 2 opérandes. J'ai une légère amélioration à faire revenir plus vite:

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

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

0
Gavriel Feria

Il existe quelques méthodes, mais la méthode ternaire (a?! B: b) semble fonctionner mieux. De plus, définir Boolean.prototype.xor semble être une option possible si vous devez effectuer des tâches fréquentes.

http://jsperf.com/xor-implementations

0
Fordi

Vous pourriez faire ceci:

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

Le résultat est le résultat d'une opération XOR.

0
Zack

Voici une fonction XOR qui prend un nombre variable d'arguments (y compris deux). Les arguments doivent seulement être vrais ou faux, pas true ou false.

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

Sur Chrome sur mon MacBook 2007, il s'exécute en 14 ns pour trois arguments. Curieusement, cette version légèrement différente prend 2935 ns pour trois arguments:

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