【问题标题】:Is there anyway to implement XOR in javascript无论如何在javascript中实现XOR
【发布时间】:2011-01-21 02:45:01
【问题描述】:

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

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

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

谢谢。

【问题讨论】:

  • 我明白这是一个很好的问题,但我强烈反对第一个答案是最好的。如果向下滚动,还有更简单的解决方案...

标签: javascript validation xor


【解决方案1】:

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


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

【讨论】:

  • 太棒了!其实,就是这么简单!为什么我之前没有听到任何人这么说?
  • 这应该是公认的答案。 所以对读者来说比使用否定和按位异或更清楚。
【解决方案2】:

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

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

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

编辑:

致力于@Jeff Meatball Yang solution

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

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

【讨论】:

  • 谢谢,我会使用这个建议。
  • 只是另一个想法:我喜欢使用按位异或,因为我认为三元运算符对于其他人来说更难阅读/理解为异或。
  • !x ^ !y 实际上是 x 和 y 的 XNOR。 !(!x ^ !y) 将是 XOR。
  • “最干净最好的”(引自jonathonhill.net/2009-02-12/logical-xor-in-javascript):((test1) != (test2))
  • @Trey 答案中使用的!x ^ !y 是XOR 的正确表述- NXOR 将是逻辑等价,XOR 的否定,因此!( !x ^ !y )。这个fiddle 显示了!x ^ !y!( !x ^ !y ) 的真值表——前者符合XOR,后者符合NXOR。 @Jamie !!x ^ !!y 可以代替 XOR (!x ^ !y),但不能代替 !( !x ^ !y )
【解决方案3】:

您正在对布尔值进行 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

【讨论】:

  • 思考你的答案...为什么不 !isEmptyString(firstStr) ^ !isEmptyString(secondStr)
【解决方案4】:

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

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

它适用于您的示例,因为布尔值 truefalse 被转换为 10,因为位运算符使用 32 位整数。

该表达式还将返回01,并且该值将被if 语句强制返回为布尔值。

您应该知道上述方法会发生类型强制,如果您正在寻找良好的性能,我不建议您使用按位运算符,您也可以使用一个简单的函数来完成它只有布尔逻辑运算符:

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


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

【讨论】:

    【解决方案5】:

    更简单的一种方法:

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

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

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

    第二个选项,如果您注意到 x != y 的计算结果为 XOR,那么您必须做的就是

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

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

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

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

    【讨论】:

    • 你知道如果 x 和 y 都为假,那么它应该评估为假,对吧? x=0 和 y=0 应评估为 false,因此您的两个示例都不是 XOR 的实现。
    • 第一个我不明白为什么它是错误的:false&false 计算结果为 false,true&true 计算结果也为 false,因为它们都加到 2 的倍数......而且,对于第二个一,x!=y 仅在一个变量为真而另一个不是时才计算为真。即使0!=FALSE 评估为FALSE,所以我不明白你的意思,抱歉......
    • 老实说,我不知道我为什么会这样想,对此感到抱歉,你是对的。这些都是简洁明了的解决方案。
    【解决方案6】:

    结帐this javascript 中异或的不同实现的解释。

    在这里简单总结一下:

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

    【讨论】:

    • 能否请您在此处提供答案,而不是让用户离开网站以获得他们想要的东西?
    • @Jonathan Sampson - 如果您认为这会有所帮助,我可以。但是将代码复制到帖子中的确切原因是什么?资源已存在
    • @foadie:因为 Stack Overflow 用于答案,而不是答案链接。如果您的链接明天断开,您的答案将失去 all 价值。
    • @Jonathan Sampson - 接受批评
    • @froadie:谢谢。好多了:)
    【解决方案7】:

    引自this文章:

    很遗憾,JavaScript 没有逻辑异或运算符。

    您可以通过以下方式“模拟” XOR 运算符的行为:

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

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

    【讨论】:

    • 能否请您在此处提供答案,而不是让用户离开网站以获得他们想要的东西?
    • 复制粘贴?不。您为什么不在这里解释相同(或相似)的解决方案,以使遇到此问题的人受益。如果您的链接明天断开,那么您的回答将毫无用处。
    • 好文章。最佳答案在页面底部。为什么不只是发布一个简短的解释?
    • ! 是不必要的,你需要做的就是测试不等式。
    【解决方案8】:

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

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

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

    【讨论】:

      【解决方案9】:

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

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

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

      【讨论】:

        【解决方案10】:

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

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

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

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

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

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

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

        XOR 的一般形式可以是函数 (truth table fiddle):

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

        你的具体例子是:

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

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

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

        【讨论】:

          【解决方案11】:

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

          干杯

          【讨论】:

          • 布尔值强制转换为 1 和 0,如您所料,因此您可以将 XOR 运算符与布尔值一起使用。
          【解决方案12】:

          这是一个可以容纳两个到多个参数的 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;
          }
          

          【讨论】:

          • XOR 应用于许多参数如果参数的数量是奇数则定义为真,否则为假。你不能提前退出。
          【解决方案13】:

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

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

          这适用于任何类型

          【讨论】:

          • 不就是和... return (x!==y); ...一样吗?
          【解决方案14】:

          这是一个 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;
          }
          

          【讨论】:

            【解决方案15】:

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

            【讨论】:

              【解决方案16】:

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

              http://jsperf.com/xor-implementations

              【讨论】:

                【解决方案17】:

                你可以这样做:

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

                其结果是异或运算的结果。

                【讨论】:

                  【解决方案18】:

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

                  【讨论】:

                    猜你喜欢
                    • 2018-03-06
                    • 2016-01-01
                    • 1970-01-01
                    • 2016-12-03
                    • 1970-01-01
                    • 1970-01-01
                    • 2013-10-10
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多