Estoy tratando de comparar 3 valores diferentes que pueden ser 0 o más. ¿Es la única forma de hacerlo con múltiples declaraciones else-if? Esto es lo que tengo ahora, pero siento que debe haber una mejor manera:
//just A if (A > 0 && B == 0 && C == 0){//Do something} //just B else if (A == 0 && B > 0 && C == 0){//Do something} //just C else if (A == 0 && B == 0 && C > 0){//Do something} //A + B else if (A > 0 && B > 0 && C == 0){//Do something} //A + C else if (A > 0 && B == 0 && C > 0){//Do something} //B + C else if (A == 0 && B > 0 && C > 0){//Do something} //A + B + C else if (A > 0 && B > 0 && C > 0){//Do something} else {//Do something}Puede pensar que cada verificación individual produce un valor de 1 o 0 (verdadero o falso). Si los valores de la prueba son A=2, B=0, C=99, entonces la verificación A > 0 -> verdadero -> 1 y B == 0 -> falso -> 0.
Entonces, si combinamos cada variación de las tres comprobaciones para A, B y C, los resultados de los valores de prueba son los siguientes:
A == 0 && B == 0 && C == 0 -> falso, falso, falso -> 000A > 0 && B == 0 && C == 0 -> verdadero, falso, falso -> 100A == 0 && B == 0 && C > 0 -> falso, falso, verdadero -> 001A == 0 && B > 0 && C == 0 -> falso, verdadero, falso -> 010A == 0 && B > 0 && C > 0 -> falso, verdadero, verdadero -> 011A > 0 && B == 0 && C > 0 -> verdadero, falso, verdadero -> 101A > 0 && B > 0 && C == 0 -> verdadero, verdadero, falso -> 110A > 0 && B > 0 && C > 0 -> verdadero, verdadero, verdadero -> 111 Puede usar números binarios como claves para un objeto desde el cual obtener la acción que desea ejecutar. Este es el objeto de variants en el ejemplo. Puede reemplazar console.logs con la lógica real de 'hacer algo' que necesita.
Qué const key = (+!!A << 2) + (+!!B << 1) + !!C; lo hace:
!!A -> verdadero, !!B -> falso (para los valores de prueba (A=2, B=0, C=99)+true -> 1, +false -> 01<<2 -> 100 (binario) -> 4 (decimal), 0<<1 sigue siendo 0, const variants = { [0b000]() {console.log('none/default')}, [0b001]() {console.log('just C')}, [0b010]() {console.log('just B')}, [0b011]() {console.log('B+C')}, [0b100]() {console.log('just A')}, [0b101]() {console.log('A+C')}, [0b110]() {console.log('A+B')}, [0b111]() {console.log('A+B+C')}, } const A = 2; const B = 0; const C = 99; const key = (+!!A << 2) + (+!!B << 1) + !!C; variants[key]();opcion 2
Si usar números binarios y operaciones bit a bit es confuso, puede usar la representación de cadena de un número binario.
const variants = { '000': () => {console.log('none/default')}, '010': () => {console.log('just B')}, // the rest of the keys } const bitA = A ? 1 : 0; const bitB = B ? 1 : 0; const bitC = C ? 1 : 0; const key = `${bitA}${bitB}${bitC}`; variants[key]();Tiene 3 variables (a, b, c) con 2 estados posibles (> 0 o <= 0), lo que significa que tiene 2 3 = 8 casos en total. Una forma es representarlos como bits.
const toBits = (a, b, c) = { const toBit = val => val > 0 ? '1' : '0' return toBit(a) + toBit(b) + toBit(c) } const cases = { '000': () => { // do something }, '001': () => { // do something }, '010': () => { // do something }, '011': () => { // do something }, '100': () => { // do something }, '101': () => { // do something }, '110': () => { // do something }, '111': () => { // do something }, } const bitsRepresentation = toBits(a, b, c) const runCase = cases[bitsRepresentation] runCase()Otra opción es usar el interruptor de forma un poco invertida.
const aFlag = a > 0 const bFlag = b > 0 const cFlag = c > 0 switch (true) { case (!aFlag && !bFlag && !cFlag): // do something case (!aFlag && !bFlag && cFlag): // do something case (!aFlag && bFlag && !cFlag): // do something case (!aFlag && bFlag && cFlag): // do something case (aFlag && !bFlag && !cFlag): // do something case (aFlag && !bFlag && cFlag): // do something case (aFlag && bFlag && !cFlag): // do something case (aFlag && bFlag && cFlag): // do something default: // do nothing }Realmente depende de si realmente necesita distinguir estrictamente entre los 8 escenarios, pero si aún necesita los 8, supongo que podría verificar cada uno de a, b y c una vez, y asignarlos a valores booleanos en lugar de comprobándolos repetidamente:
aFlag = (A > 0); bFlag = (B > 0); cFlag = (C > 0); //just A if (aFlag && !bFlag && !cFlag){//Do something} //just B else if (!aFlag && bFlag && !cFlag){//Do something} //just C else if (!aFlag && !bFlag && cFlag){//Do something} //A + B else if (aFlag && bFlag && !cFlag){//Do something} //A + C else if (aFlag && !bFlag && cFlag){//Do something} //B + C else if (!aFlag && bFlag && cFlag){//Do something} //A + B + C else if (aFlag && bFlag && cFlag){//Do something} else {//Do something}Esto probablemente no sea mucho más rápido, pero, al menos en mi opinión, parece un poco más fácil de ver.
Supongo que también podría cambiarlo a alguna forma de declaraciones if anidadas, en lugar de una serie lineal de declaraciones else-if:
if (A > 0) { if (B > 0) { if (C > 0) { //A + B + C } else { //A + B } } else { if (C > 0) { //A + C } else { //just A } } } else { if (B > 0) { if (C > 0) { //B + C } else { //just B } } else { if (C > 0) { //just C } else { //None } } }Esto parece realmente desordenado, pero solo haría 3 comprobaciones en total, en lugar de 7 posibles para su implementación.