javascript - validaciones - ¿Simplificar una sentencia if/else?
sentencia if else en c++ (12)
Estoy tratando de simplificar lo siguiente:
function handleDirection(src) {
if (src === ''left'') {
if (inverse) {
tracker--;
} else {
tracker++;
}
} else {
if (inverse) {
tracker++;
} else {
tracker--;
}
}
}
Para reducir el número de condicionales. El src
será ''left''
o ''right''
siempre.
Ahora mismo estás comparando en cadenas, que no te aconsejaría. Si, por ejemplo, usa ''Izquierda'' en lugar de ''izquierda'', fallará la primera instrucción if. Quizás un booleano pueda ser de utilidad aquí, ya que puede garantizar que solo tiene dos estados.
Las declaraciones if en el interior se pueden comprimir a través de operadores condicionales .
Quizás algo como esto es lo que estás buscando:
const left = 1;
const right = -1;
var direction = 1;
function handleDirection(src) {
tracker += src * direction;
}
function reverse() { // (Example)
direction = direction * -1;
}
Consulte: https://jsfiddle.net/9zr4f3nv/
Desea aumentar el rastreador si uno de src == left
o inverse
es verdadero pero no el otro, y disminuirlo de otra manera, que es lo que hace el operador "XOR" ^
+-----------+---------------+---------+
| direction | windDirection | OffsetX |
+-----------+---------------+---------+
| left | right | -1 |
| left | up | 1 |
| left | down | 1 |
| left | left | 2 |
| right | up | -1 |
| right | down | -1 |
| right | right | -2 |
| right | left | 1 |
| up | up | 0 |
| up | down | 0 |
| up | left | 1 |
| up | right | -1 |
| down | up | 0 |
| down | down | 0 |
| down | left | 1 |
| down | right | -1 |
+-----------+---------------+---------+
Puedes reducirlo aún más usando una expresión ternaria:
// by using short circuiting
function handleDirection(src) {
if (src == ''left'') tracker = inverse && tracker-1 || tracker +1
else tracker = inverse && tracker+1 || tracker -1
}
// by using ternary operator
function handleDirection(src) {
if (src == ''left'') tracker = inverse ? tracker-1 : tracker +1
else tracker = inverse ? tracker+1 : tracker -1
}
O si desea evitar cualquier tipo de condición condicional, con moldes implícitos y aritmética "inteligente":
function handleDirection(src) {
if (
((src === ''left'') && !inverse) ||
((src === ''right'') && inverse)
) {
tracker++;
}
else {
tracker--;
}
}
Esto podría simplificarse a una expresión ternaria que devuelve 1
o -1
según el estado. Entonces puedes agregar eso al tracker
.
function handleDirection(src) {
var delta = (src === ''left'' && inverse) || (src !== ''left'' && !inverse) ? -1 : 1;
tracker += delta;
}
Esto podría simplificarse aún más utilizando la lógica que @NinaScholz señaló en su respuesta:
function handleDirection(src) {
var delta = (src === ''left'') === inverse ? -1 : 1;
tracker += delta;
}
Esto tiene solo un condicional, y me parece que se lee más intuitivamente que las otras respuestas:
+-----------+------------+--------+
| direction | isInverted | Offset |
+-----------+------------+--------+
| left | true | -1 |
| left | false | 1 |
| right | true | 1 |
| right | false | -1 |
| up | false | 0 |
| up | true | 0 |
| down | false | 0 |
| down | true | 0 |
+-----------+------------+--------+
Incluso puedes hacerlo con una sola línea de código:
function getDirectionOffset(src) {
tracker += (src === ''left'' ? 1 : -1) * (inverse ? -1 : 1);
}
No me gustan los cielos y trato de evitar anidar si es posible. Creo que esto transmite la idea de lo inverse
de una manera más natural:
function handleDirection(src) {
tracker += (src == "left" ? 1 : -1) * (inverse ? -1 : 1);
};
Podrías consultar con el resultado de la primera comprobación.
Este es un cheque O exclusivo.
// typeof inverse === ''boolean''
function handleDirection(src) {
if (src === ''left'' === inverse) {
tracker--;
} else {
tracker++;
}
}
La verificación evalúa la expresión en este orden (src === ''left'') === inverse
:
src === ''left'' === inverse
---- first --- returns a boolean value
--------- second --------- take result of former check & compairs it with another boolean
Puede usar una estructura de datos de tipo de matriz bidimensional desde js y almacenar los resultados deseados en el índice seg e inverso. O JSON.
Puede utilizar sintaxis de cortocircuito o operadores ternarios.
let tracker = 0;
let invert = false;
const movementLookupTable = {
"true": { },
"false": { },
}
//it can be initialised as part of the above expression but this is more readable
movementLookupTable[true ][true ] = -1;
movementLookupTable[true ][false] = 1;
movementLookupTable[false][true ] = 1;
movementLookupTable[false][false] = -1;
function handleDirection(src) {
const offset = movementLookupTable[src === "left"][invert];
tracker += offset;
}
// usage
invert = true;
handleDirection("left");
handleDirection("left");
handleDirection("right");
console.log(tracker);
Suponiendo que lo inverse
es una bandera que establecería una vez, entonces no necesita tenerla en cuenta cada vez, puede calcular su impacto una vez y simplemente usarla tal como está, lo que reducirá la lógica y las ramas de su código. Si desea cambiarlo a medida que avanza, es posible que deba separar la lógica para el cálculo para poder reutilizarlo.
También puede extraer la dirección del movimiento en una función autónoma y su handleDirection
la handleDirection
vuelve muy simple: calcula la dirección a la que desea ir en función de la handleDirection
y la invert
.
function handleDirection(src) {
if (src === ''left'' ^ inverse) {
tracker++;
} else {
tracker--;
}
}
Dicho esto, todo esto sugiere que no debería usar una función, o debería usarla de manera diferente. Puede recopilar toda esa funcionalidad en una clase o, en su lugar, pasar toda la información sobre las funciones, por lo que no tiene elementos globales. Aquí hay un ejemplo de implementación orientada a objetos del concepto:
function handleDirection(src) {
tracker += src === ''left'' ^ inverse ? 1 : -1;
}
Por cierto, otra alternativa es NO calcular el movimiento cada vez. Realmente sabes lo que está sucediendo cada vez; en efecto, tienes una tabla de verdad donde tus entradas son src === left
e inverse
y las salidas son la forma en que modificas tu seguimiento.
function handleDirection(src) {
tracker += 1 - 2 * (src === ''right'' ^ inverse); // either 1-0=1 or 1-2=-1
}
Entonces, puedes poner esa mesa.
let tracker = 0;
//extract logic for the movement offset based on direction
function getDirectionOffset(src) {
return src === ''left'' ? 1 : -1;
}
//have a setter for the invert property
function setInverse(isInverse) {
movementModifier = isInverse ? -1 : 1
}
//declare the variable dependent on the inverse property
let movementModifier;
//initialise movementModifier variable
setInverse(false);
function handleDirection(src) {
const offset = getDirectionOffset(src) * movementModifier;
tracker += offset;
}
// usage
setInverse(true);
handleDirection("left");
handleDirection("left");
handleDirection("right");
console.log(tracker);
En este caso, podría ser una exageración, pero este enfoque podría ser útil si hay más banderas (incluidos más valores para las banderas) y / o estados finales. Por ejemplo, tal vez desee introducir cuatro direcciones, pero no modifica el valor del tracker
si está up
o down
.
class TrackerMover {
constructor(inverse) {
this.tracker = 0;
this.movementModifier = inverse ? 1 : -1
}
handleDirection(src) {
const offset = this.getDirectionOffset(src) * this.movementModifier;
this.tracker += offset;
}
getDirectionOffset(src) {
return src === ''left'' ? -1 : 1;
}
getPosition() {
return this.tracker;
}
}
//usage
const mover = new TrackerMover(true);
mover.handleDirection("left");
mover.handleDirection("left");
mover.handleDirection("right");
console.log(mover.getPosition())
Como puedes ver, ahora no solo son booleanos, puedes manejar cualquier valor. Usando una tabla, también cambia la invert
para convertirla en algo así como windDirection
, por lo que si el movimiento se left
y la windDirection
es right
, el resultado es como lo que es ahora, pero podría tener la dirección de la left
y el viento en dirección a la left
, por lo que seguir adelante O puede moverse up
y dejar la dirección del viento para que el tracker
(en este punto las coordenadas X) se modifique realmente.
+--------+------------+--------+
| isLeft | isInverted | Offset |
+--------+------------+--------+
| true | true | -1 |
| true | false | 1 |
| false | true | 1 |
| false | false | -1 |
+--------+------------+--------+
Con cuatro direcciones y cuatro direcciones de viento para tener en cuenta, la lógica puede ser bastante molesta tanto para leer como para mantener en el futuro, mientras que si solo tiene una tabla de búsqueda, es fácil y puede extenderlo fácilmente para manejar diagonales (supongamos que cambian el valor en 0.5
lugar de 1
) y a su algoritmo realmente no le importará siempre y cuando solo obtenga los valores de la tabla.
Usted no necesita ninguna oración if
en absoluto. La misma operación se puede realizar calculando un incremento positivo o negativo dependiendo de src e inverso con solo la ayuda del operador ternario.
const LEFT = ''left''
const RIGHT = ''right''
function handleMovement(src) {
tracker += movementIncrement(src, inverse)
}
function movementIncrement(direction, inverse) {
if (inverse) {
direction = inverseDirection(direction)
}
return LEFT ? -1 : +1
}
function inverseDirection(direction) {
return direction === LEFT ? RIGHT : LEFT
}
Por cierto En aras de la eficiencia, recomendaría el uso directo de incrementos / decrementos numéricos en lugar de cadenas que requieren un procesamiento adicional para ser decodificado. Puedes usar constantes para lograr la misma legibilidad:
También se puede optimizar el inverso como un valor numérico que cambia entre 1 (no invertido) y -1 (invertido).
function handleDirection(src)
{
let change = 1;
if (''right'' == src)
change = -1;
if (inverse)
change = -change;
tracker += change;
}
... incluso si las palabras clave "derecha" e "izquierda" provienen de algún tipo de entrada textual del usuario, simplemente puede traducirlas desde un diccionario:
function handleDirection(src) {
if (src) {
inverse ? tracker-- : tracker++;
} else {
inverse ? tracker++ : tracker--;
}
}
function handleDirection(src) {
var movement = 1;
if(src === ''left'')
movement = -1;
if(inverse)
tracker += movement;
else
tracker -= movement;
}