Pregunta

Estoy tratando de implementar XOR en JavaScript de la siguiente manera:

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

¿Hay una mejor manera de hacer esto en JavaScript?

Gracias.

¿Fue útil?

Solución

Fingido que estás buscando un Xor lógico, ya que JavaScript ya tiene uno bitwise (^) :)

Normalmente uso un operador ternario simple (una de las raras veces que uso una):

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

Editar:

Trabajando en el @Jeff Febrero Yang solución

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

Negas los valores para transformarlos en booleanos y luego aplica el operador XOR bitwise. Tal vez no sea tan mantenible como la primera solución (o tal vez estoy demasiado acostumbrado al primero)

Otros consejos

Como otros han señalado, Logical Xor es lo mismo que no equivalente a los booleanos, por lo que puede hacer esto:


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

Está haciendo un XOR de valores booleanos que es fácil de modelar en un XOR bitwise (que tiene JavaScript):

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

if(a ^ b) { ... }

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

Puede usar el operador XOR bitwise (^) directamente:

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

Funcionará para su ejemplo desde el booleano true y false Los valores se convierten en 1 y 0 Porque los operadores bit a bit trabajan con enteros de 32 bits.

Esa expresión también volverá 0 o 1, y ese valor será obligado a Boolean por el if declaración.

Debe conocer la coerción de tipo que ocurre con el enfoque anterior, si está buscando un buen rendimiento, no le recomendaría que trabaje con los operadores bit a bit, también puede hacer una función simple para hacerlo usando solo boolean lógico lógico Operadores:

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


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

Más fácil un método:

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

asumiendo, por supuesto, que ambas variables son verdaderos booleanos, es decir, 1 o 0.

  • Si x === y Obtendrá un número uniforme, por lo que Xor será 0.
  • Y si x !== y Entonces obtendrás un número impar, por lo que Xor será 1 :)

Una segunda opción, si notas que x != y evalúa como un XOR, entonces todo lo que debes hacer es

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

Que solo evaluará, nuevamente, como un XOR. (Me gusta esto mucho mejor)

Por supuesto, una buena idea sería implementar esto en una función, pero es solo su elección.

¡Espero que alguno de los dos métodos ayude a alguien! Marco esta respuesta como wiki de la comunidad, por lo que se puede mejorar.

Verificar este Explicación de diferentes implementaciones de XOR en JavaScript.

Solo para resumir algunos de ellos aquí mismo:

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

O

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

O

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

O

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

Cotizando de este artículo:

Desafortunadamente, JavaScript no tiene un operador lógico de XOR.

Puede "emular" el comportamiento del operador XOR con algo como:

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

El artículo vinculado analiza un par de enfoques alternativos.

Xor solo significa "¿Son estos dos valores booleanos diferentes?". Por lo tanto:

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

los !!s son solo para garantizar que el != El operador compara dos valores booleanos genuinos, ya que posiblemente isEmptyString() Devuelve algo más (como null para falso, o la cadena en sí para verdadero).

Suponiendo que está buscando el XOR booleano, aquí hay una implementación simple.

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

Lo anterior deriva de la definición de una "disyunción exclusiva" {cualquiera de los dos, pero no ambas}.

Dado que los valores booleanos true y false se convierten en 1 y 0 respectivamente, cuando se usan operadores bit a ellos, el bitwise-xor ^ Puede hacer doble servicio como un XOR lógico y un bitwiseone, siempre que sus valores sean valores booleanos (los valores "verdaderos" de JavaScript no funcionan). Esto es fácil de lograr con la negación ! operador.

a XOR b es lógicamente equivalente a la siguiente lista (corta) de expresiones:

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

Hay muchas otras formas posibles, como !a ? !!b : !b - Pero estos dos patrones tienen la ventaja de evaluar solo a y b Una vez cada uno (y no "cortocircuitar" también si a es falso y, por lo tanto, no evalúa b), mientras se forman usando ternary ?:, O ||, o y && Los operadores serán de doble evaluación o cortocircuito.

La negación ! Los operadores en ambas declaraciones es importante incluir por un par de razones: convierte todos los valores "verdaderos" en valores booleanos ("" -> falso, 12 -> verdadero, etc.) para que el operador bit a bit tenga valores con los que pueda trabajar, Entonces la desigualdad != El operador solo compara el valor de verdad de cada expresión (a != b no funcionaría correctamente si a o b eran cadenas no igual, no vacías, etc.), y para que cada evaluación devuelva un resultado del valor booleano en lugar del primer valor "verdady".

Puede seguir expandiendo estos formularios agregando dobles negaciones (o la excepción, !!a ^ !!b, que todavía es equivalente a XOR), pero tenga cuidado al negar solo parte de la expresión. Estas formas pueden parecer a primera vista de "trabajar" si está pensando en términos de distribución en aritmático (donde 2(a + b) == 2a + 2b, etc.), pero de hecho produce diferentes tablas de verdad de Xor (estos producen resultados similares a Logical NXOR):

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

La forma general para Xor, entonces, podría ser la función (Videra de la mesa de la verdad):

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

Y su ejemplo específico sería:

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

O si isEmptyString Devuelve solo los valores booleanos y no quieres un general xor función, simplemente:

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

JavaScript no tiene un operador lógico de XOR, por lo que su construcción parece plausible. Si hubieran sido números, entonces podrías haber usado ^ es decir, el operador XOR bitwise.

salud

Aquí hay un XOR que puede acomodarse de dos a muchos argumentos

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

Ejemplo de uso:

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

Espero que este sea el más corto y limpio

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

Esto funcionará para cualquier tipo

Aquí hay una función XOR que toma un número variable de argumentos (incluidos dos). Los argumentos solo necesitan ser verdaderos o falsos, no true o false.

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

En Chrome en mi MacBook 2007, se ejecuta en 14 ns para tres argumentos. Curiosamente, esta versión ligeramente diferente toma 2935 ns para tres argumentos:

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

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

Hay algunos métodos, pero el método ternario (A? Además, configurar boolean.prototype.xor parece ser una opción si necesita XOR cosas con frecuencia.

http://jsperf.com/xor-implementations

Podrías hacer esto:

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

El resultado de eso es el resultado de una operación XOR.

@George, me gusta su función por su capacidad de llevar más de 2 operandos. Tengo una ligera mejora para que regrese más rápido:

function xor() {
    for (var i=arguments.length-1, trueCount=0; i>=0; --i)
        if (arguments[i]) {
            if (trueCount)
                return false
            ++trueCount;
        }
    return trueCount & 1;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top