operadores - ¿Hay alguna forma de implementar XOR en javascript?
operadores de asignacion en javascript (18)
@george, me gusta tu función por su capacidad para tomar más de 2 operandos. Tengo una ligera mejora para que vuelva 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;
}
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.
Aquí hay una función XOR que toma una cantidad variable de argumentos (incluidos dos). Los argumentos solo necesitan ser verdaderos o falsos, no true
ni 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 tiene 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;
}
Citando de http://www.howtocreate.co.uk/xor.html artículo:
Desafortunadamente, JavaScript no tiene un operador XOR lógico.
Puede "emular" el comportamiento del operador XOR con algo como:
if( !foo != !bar ) {
...
}
El artículo vinculado discute un par de enfoques alternativos.
Como otros han señalado, el XOR lógico es el mismo que el no igual para los booleanos, por lo que puede hacer esto:
// XOR validation
if( isEmptyString(firstStr) != isEmptyString(secondStr) )
{
alert(SOME_VALIDATION_MSG);
return;
}
Consulte http://www.howtocreate.co.uk/xor.html explicación de las diferentes implementaciones de XOR en javascript.
Solo para resumir algunos de ellos aquí:
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;
}
Dado que los valores booleanos true
y false
se convierten a 1
y 0
respectivamente cuando se utilizan operadores bitwise en ellos, el bit-XOR ^
puede hacer doble tarea como un XOR lógico y una bitwise, siempre y cuando los valores sean valores booleanos ( Los valores de "verdad" de Javascript no funcionarán). ¡Esto es fácil de lograr con la negación !
operador.
a XOR b
es lógicamente equivalente a la siguiente lista (breve) de expresiones:
!a ^ !b;
!a != !b;
Hay muchas otras formas posibles, como !a ? !!b : !b
!a ? !!b : !b
- pero estos dos patrones tienen la ventaja de solo evaluar a
y b
una vez cada uno (y tampoco "cortocircuitarán" si a
es falso y por lo tanto no evalúa b
), mientras que las formas usan ternario ?:
, O ||
, o los operadores AND &&
harán una doble evaluación o un cortocircuito.
¡La negación !
es importante incluir operadores en ambas sentencias por un par de razones: convierte todos los valores "verídicos" en valores booleanos ("" -> falso, 12 -> verdadero, etc.) para que el operador bit a bit tenga valores con los que pueda trabajar, entonces el operador de desigualdad !=
solo compara el valor de verdad de cada expresión ( a != b
no funcionaría correctamente si a
o b
fueran cadenas no vacías, no vacías, etc.), y para que cada evaluación arroje un resultado de valor booleano del primer valor de "verdad".
Puede seguir expandiendo estos formularios agregando negaciones dobles (o la excepción, !!a ^ !!b
, que aún es equivalente a XOR), pero tenga cuidado al negar solo una parte de la expresión. A primera vista, estas formas pueden "funcionar" si estás pensando en términos de distribución en aritmático (donde 2(a + b) == 2a + 2b
, etc.), pero de hecho producen diferentes tablas de verdad de XOR ( fiddle ):
!( a ^ b )
!( !!a ^ !!b )
!!a == !!b
La forma general para XOR, entonces, podría ser la función ( fiddle ):
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 valores booleanos y no desea una función general xor
, simplemente:
if ( isEmptyString( firstStr ) ^ isEmptyString( secondStr ) ) { ... }
Espero que este sea el más corto y limpio
function xor(x,y){return true==(x!==y);}
Esto funcionará para cualquier tipo
Está haciendo un XOR de valores booleanos que es fácil de modelar en un XOR bit a bit (que tiene Javascript):
var a = isEmptyString(firstStr) ? 1 : 0;
var b = isEmptyString(secondStr) ? 1 : 0;
if(a ^ b) { ... }
Finjo que estás buscando un XOR lógico, ya que javascript ya tiene uno bit a bit (^) :)
Usualmente uso un operador ternario simple (una de las raras veces que uso uno):
if ((isEmptyString(firstStr) ? !isEmptyString(secondStr)
: isEmptyString(secondStr))) {
alert(SOME_VALIDATION_MSG);
return;
}
Editar:
trabajando en la solución @Jeff Meatball Yang
if ((!isEmptyString(firstStr) ^ !isEmptyString(secondStr))) {
alert(SOME_VALIDATION_MSG);
return;
}
usted niega los valores para transformarlos en booleanos y luego aplica el operador xor bit a bit. Tal vez no sea tan fácil de mantener como la primera solución (o tal vez estoy demasiado acostumbrado a la primera)
Hay algunos métodos, pero el método ternario (a?! B: b) parece funcionar mejor. Además, la configuración de Boolean.prototype.xor parece ser una opción si necesita xor cosas a menudo.
Intenta esto: function xor(x,y) var result = x || y if (x === y) { result = false } return result }
function xor(x,y) var result = x || y if (x === y) { result = false } return result }
Javascript no tiene un operador XOR lógico, por lo que su construcción parece plausible. Si se tratara de números, entonces podría haber usado ^, es decir, el operador XOR a nivel de bit.
aclamaciones
Método más fácil:
if ((x+y) % 2) {
//statement
}
suponiendo por supuesto que ambas variables son verdaderas booleanas, es decir, 1
o 0
.
- Si
x === y
obtendrás un número par, entonces XOR será0
. - Y si
x !== y
entonces obtendrás un número impar, entonces XOR será1
:)
Una segunda opción, si observa que x != y
evalúa como XOR, entonces todo lo que debe hacer es
if (x != y) {
//statement
}
Lo cual simplemente evaluará, nuevamente, como un XOR. (Me gusta mucho mejor)
Por supuesto, una buena idea sería implementar esto en una función, pero es solo tu elección.
Espero que cualquiera de los dos métodos ayude a alguien. Marqué esta respuesta como wiki de la comunidad, por lo que puede mejorarse.
Podrías hacer esto:
Math.abs( isEmptyString(firstStr) - isEmptyString(secondStr) )
El resultado de eso es el resultado de una operación XOR.
Puede usar el operador XOR bit a bit ( ^
) directamente:
if (isEmptyString(firstStr) ^ isEmptyString(secondStr)) {
// ...
}
Funcionará para su ejemplo dado que los valores booleanos true
y false
se convierten en 1
y 0
porque los operadores bit a bit trabajan con enteros de 32 bits.
Esa expresión también devolverá 0
o 1
, y la declaración if
forzará de nuevo a Boolean.
Debe tener en cuenta la coerción de tipo que se produce con el enfoque anterior, si está buscando un buen rendimiento, no le recomendaría que trabaje con los operadores bit a bit, también podría hacer una función simple para hacerlo utilizando solo lógica booleana operadores:
function xor(x, y) {
return (x || y) && !(x && y);
}
if (xor(isEmptyString(firstStr), isEmptyString(secondStr))) {
// ...
}
Suponiendo que está buscando BOOLEAN XOR, aquí hay una implementación simple.
function xor(expr1, expr2){
return ((expr1 || expr2) && !(expr1 && expr2));
}
Lo anterior se deriva de la definición de "disyunción exclusiva" {cualquiera de uno, pero no ambos}.
XOR solo significa "¿son estos dos valores booleanos diferentes?". Por lo tanto:
if (!!isEmptyString(firstStr) != !!isEmptyString(secondStr)) {
// ...
}
El !!
s solo para garantizar que el operador !=
compare dos valores booleanos genuinos, ya que concebiblemente isEmptyString()
devuelve algo más (como null
para falso o la cadena para verdadero).
aquí hay un XOR que puede acomodar 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;
}