42

我正在尝试通过以下方式在 javascript 中实现 XOR:

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

有没有更好的方法在javascript中做到这一点?

谢谢。

4

18 回答 18

56

正如其他人指出的那样,逻辑 XOR 与布尔值的不相等相同,因此您可以这样做:


  // XOR validation
  if( isEmptyString(firstStr) != isEmptyString(secondStr) )
    {
      alert(SOME_VALIDATION_MSG);
      return;
    }
于 2010-02-25T17:50:00.873 回答
34

我假装您正在寻找一个逻辑 XOR,因为 javascript 已经有一个按位 (^) :)

我通常使用一个简单的三元运算符(我很少使用一个):

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

编辑:

致力于@Jeff Meatball Yang解决方案

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

您否定这些值以便将它们转换为布尔值,然后应用按位异或运算符。也许它不像第一个解决方案那样可维护(或者我对第一个解决方案太习惯了)

于 2010-02-25T17:18:10.007 回答
11

您正在对布尔值进行 XOR,这很容易建模为按位 XOR(Javascript 具有):

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

if(a ^ b) { ... }

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

于 2010-02-25T17:16:52.070 回答
8

您可以直接使用按位 XOR 运算符 ( ^):

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

它适用于您的示例,因为布尔值truefalse值已转换为1,并且0按位运算符适用于 32 位整数。

该表达式也将返回0or 1,并且该值将被if语句强制返回布尔值。

您应该注意使用上述方法发生的类型强制,如果您正在寻找良好的性能,我不建议您使用按位运算符,您也可以制作一个简单的函数来仅使用布尔逻辑运营商:

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


if (xor(isEmptyString(firstStr), isEmptyString(secondStr))) {
  // ...
}
于 2010-02-25T17:21:01.170 回答
7

更简单的一种方法:

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

当然,假设这两个变量都是真正的布尔值,即10

  • 如果x === y你得到一个偶数,那么 XOR 将是0.
  • 如果x !== y那时你会得到一个奇数,那么 XOR 将是1:)

第二种选择,如果您注意到它的x != y计算结果为 XOR,那么您所要做的就是

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

这将再次评估为 XOR。(我更喜欢这个)

当然,一个好主意是将其实现为一个函数,但这只是您的选择。

希望这两种方法中的任何一种对某人有所帮助!我将此答案标记为社区 wiki,因此可以对其进行改进。

于 2013-01-28T01:26:40.047 回答
5

查看这个对 javascript 中 XOR 的不同实现的解释。

在这里总结其中的一些:

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

或者

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

或者

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

或者

if( !isEmptyString(firstStr)!= !isEmptyString(secondStr)) {
   alert(SOME_VALIDATION_MSG); 
   return;
}
于 2010-02-25T17:16:07.813 回答
5

引用这篇文章:

不幸的是,JavaScript 没有逻辑 XOR 运算符。

您可以使用以下内容“模拟” XOR 运算符的行为:

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

链接的文章讨论了几种替代方法。

于 2010-02-25T17:16:11.993 回答
2

XOR 只是意味着“这两个布尔值不同吗?”。所以:

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

!!s 只是为了保证运算符比较两个真正的!=布尔值,因为可以想象isEmptyString()返回其他东西(如nullfalse,或字符串本身为 true)。

于 2010-02-25T17:27:28.410 回答
2

假设您正在寻找 BOOLEAN XOR,这里有一个简单的实现。

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

以上来自“排他性析取”的定义{其中之一,但不是两者}。

于 2013-08-21T22:04:13.853 回答
2

由于布尔值true和在对它们使用按位运算符时分别false转换为10,因此按位异或^可以作为逻辑异或和按位执行双重任务,只要您的值是布尔值(Javascript的“真实”值不会工作)。使用否定!运算符很容易实现这一点。

a XOR b在逻辑上等价于以下(短)表达式列表:

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

还有很多其他可能的形式 - 例如!a ? !!b : !b- 但是这两种模式的优点是只评估aand一次(如果是 false 并且因此不会评估,b也不会“短路” ),而使用 ternary , OR ,或 AND运算符将进行双重评估或短路。ab?:||&&

两个语句中的否定!运算符很重要,包括以下几个原因:它将所有“真实”值转换为布尔值(“”-> false、12-> true 等),以便按位运算符具有可以工作的值with,所以不等式!=运算符只比较每个表达式的真值(a != b如果ab不相等,非空字符串等将无法正常工作),因此每个评估返回一个布尔值结果而不是第一个“真”价值。

您可以通过添加双重否定(或例外,!!a ^ !!b仍然等价于 XOR)来继续扩展这些形式,但在否定表达式的一部分时要小心。如果您考虑算术分布( where 等),这些形式乍一看似乎“有效” 2(a + b) == 2a + 2b,但实际上从 XOR 产生不同的真值表(这些产生与逻辑 NXOR 相似的结果):

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

那么,异或的一般形式可以是函数(真值表小提琴):

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

然后您的具体示例将是:

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

或者,如果isEmptyString只返回布尔值并且您不需要通用xor函数,只需:

if ( isEmptyString( firstStr ) ^ isEmptyString( secondStr ) ) { ... }
于 2013-12-21T22:05:46.057 回答
1

Javascript 没有逻辑 XOR 运算符,因此您的构造似乎是合理的。如果它是数字,那么您可以使用 ^ 即按位异或运算符。

干杯

于 2010-02-25T17:18:04.137 回答
1

这是一个可以容纳两个到多个参数的 XOR

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

使用示例:

if ( XOR( isEmptyString(firstStr), isEmptyString(secondStr) ) ) {
    alert(SOME_VALIDATION_MSG);
    return;
}
于 2011-02-14T21:59:35.607 回答
1

我希望这将是最短和最干净的

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

这适用于任何类型

于 2013-05-18T10:09:46.420 回答
0

这是一个 XOR 函数,它接受可变数量的参数(包括两个)。论点只需要是真或假,而不是truefalse

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

在我的 2007 MacBook 上的 Chrome 上,三个参数的运行时间为 14 ns。奇怪的是,这个略有不同的版本需要 2935 ns 来处理三个参数:

function xorSlow() {
    for (var i=arguments.length-1, result=false; i>=0; --i)
        if (arguments[i])
            result ^= true;
    return result;
}
于 2012-09-29T03:32:43.790 回答
0

试试这个: function xor(x,y) var result = x || y if (x === y) { result = false } return result }

于 2012-12-26T02:27:14.610 回答
0

有几种方法,但三元方法 (a ? !b : b) 似乎表现最好。此外,如果您需要经常对事物进行异或,设置 Boolean.prototype.xor 似乎是一种选择。

http://jsperf.com/xor-implementations

于 2013-12-17T16:37:46.640 回答
0

你可以这样做:

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

其结果是 XOR 操作的结果。

于 2013-12-20T16:50:32.557 回答
0

@george,我喜欢你的函数,因为它能够接受两个以上的操作数。我有一个小的改进,使其返回更快:

function xor() {
    for (var i=arguments.length-1, trueCount=0; i>=0; --i)
        if (arguments[i]) {
            if (trueCount)
                return false
            ++trueCount;
        }
    return trueCount & 1;
}
于 2015-06-02T09:02:01.997 回答