开发者

Is there anyway to implement XOR in javascript

I'm trying to implement XOR in javascript in the fol开发者_如何学Clowing way:

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

Is there a better way to do this in javascript?

Thanks.


As others have pointed out, logical XOR is the same as not-equal for booleans, so you can do this:


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


I pretend that you are looking for a logical XOR, as javascript already has a bitwise one (^) :)

I usually use a simple ternary operator (one of the rare times I use one):

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

Edit:

working on the @Jeff Meatball Yang solution

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

you negate the values in order to transform them in booleans and then apply the bitwise xor operator. Maybe it is not so maintainable as the first solution (or maybe I'm too accustomed to the first one)


You are doing an XOR of boolean values which is easy to model into a bitwise XOR (which Javascript has):

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

if(a ^ b) { ... }

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


You could use the bitwise XOR operator (^) directly:

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

It will work for your example since the boolean true and false values are converted into 1 and 0 because the bitwise operators work with 32-bit integers.

That expression will return also either 0 or 1, and that value will be coerced back to Boolean by the if statement.

You should be aware of the type coercion that occurs with the above approach, if you are looking for good performance, I wouldn't recommend you to work with the bitwise operators, you could also make a simple function to do it using only Boolean logical operators:

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


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


Easier one method:

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

assuming of course that both variables are true booleans, that is, 1 or 0.

  • If x === y you'll get an even number, so XOR will be 0.
  • And if x !== y then you'll get an odd number, so XOR will be 1 :)

A second option, if you notice that x != y evaluates as a XOR, then all you must do is

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

Which will just evaluate, again, as a XOR. (I like this much better)

Of course, a nice idea would be to implement this into a function, but it's your choice only.

Hope any of the two methods help someone! I mark this answer as community wiki, so it can be improved.


Checkout this explanation of different implementations of XOR in javascript.

Just to summarize a few of them right here:

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;
}


Quoting from this article:

Unfortunately, JavaScript does not have a logical XOR operator.

You can "emulate" the behaviour of the XOR operator with something like:

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

The linked article discusses a couple of alternative approaches.


XOR just means "are these two boolean values different?". Therefore:

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

The !!s are just to guarantee that the != operator compares two genuine boolean values, since conceivably isEmptyString() returns something else (like null for false, or the string itself for true).


Assuming you are looking for the BOOLEAN XOR, here is a simple implementation.

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

The above derives from the definition of an "exclusive disjunction" {either one, but not both}.


Since the boolean values true and false are converted to 1 and 0 respectively when using bitwise operators on them, the bitwise-XOR ^ can do double-duty as a logical XOR as well as a bitwiseone, so long as your values are boolean values (Javascript's "truthy" values wont work). This is easy to acheive with the negation ! operator.

a XOR b is logially equivalent to the following (short) list of expressions:

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

There are plenty of other forms possible - such as !a ? !!b : !b - but these two patterns have the advantage of only evaluating a and b once each (and will not "short-circuit" too if a is false and thus not evaluate b), while forms using ternary ?:, OR ||, or AND && operators will either double-evaluate or short-circuit.

The negation ! operators in both statements is important to include for a couple reasons: it converts all "truthy" values into boolean values ( "" -> false, 12 -> true, etc.) so that the bitwise operator has values it can work with, so the inequality != operator only compares each expression's truth value (a != b would not work properly if a or b were non-equal, non-empty strings, etc.), and so that each evaluation returns a boolean value result instead of the first "truthy" value.

You can keep expanding on these forms by adding double negations (or the exception, !!a ^ !!b, which is still equivalent to XOR), but be careful when negating just part of the expression. These forms may seem at first glance to "work" if you're thinking in terms of distribution in arithmatic (where 2(a + b) == 2a + 2b, etc.), but in fact produce different truth tables from XOR (these produce similar results to logical NXOR):

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

The general form for XOR, then, could be the function (truth table fiddle):

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

And your specific example would then be:

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

Or if isEmptyString returns only boolean values and you don't want a general xor function, simply:

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


Javascript does not have a logical XOR operator, so your construct seems plausible. Had it been numbers then you could have used ^ i.e. bitwise XOR operator.

cheers


here's an XOR that can accommodate from two to many arguments

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

Example of use:

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


I hope this will be the shortest and cleanest one

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

This will work for any type


Here is an XOR function that takes a variable number of arguments (including two). The arguments only need to be truthy or falsy, not true or false.

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

On Chrome on my 2007 MacBook, it runs in 14 ns for three arguments. Oddly, this slightly different version takes 2935 ns for three arguments:

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


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


There's a few methods, but the ternary method (a ? !b : b) appears to perform best. Also, setting Boolean.prototype.xor appears to be an option if you need to xor things often.

http://jsperf.com/xor-implementations


You could do this:

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

The result of that is the result of a XOR operation.


@george, I like your function for its capability to take in more than 2 operands. I have a slight improvement to make it return faster:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜