Y múltiples parámetros

15
function andMultipleExpr(){
  let logicalAnd;
  let i;
  for (i = 0; i < arguments.length; i++){
    logicalAnd =  arguments[i] && arguments[i+1];
  }
  return logicalAnd;
}

console.log(andMultipleExpr(true, true, false, false));

Lo que espero es ejecutar este código: verdadero && verdadero && false && false y eso debería devolver falso .

¿Cómo hacer que eso funcione en js? Gracias

Hakim Asa
fuente
Solo estoy dudando. Quiero estar seguro si mi idea está bien formulada. Si hay una mejor manera, sugiérale.
Hakim Asa
¿Cuál debería ser la salida cuando se usan valores de Troothy en lugar de booleanos? es decir, andMultipleExpr(1, 1, 0, 0)oandMultipleExpr(1, 1, 1, 1)
nick zoum
Además, ¿cuál debería ser la salida de andMultipleExpr()(Llamar a la función sin parámetros)?
Nick Zoum
bueno, esos casos también deben tenerse en cuenta. :-)
Hakim Asa

Respuestas:

16

Use Array.prototype.everyen todos los argumentos pasados ​​para verificar si todos son verdaderos;

function andMultipleExpr(...a) {
  if(a.length === 0) return false; // return false when no argument being passed
  return a.every(Boolean);
}

console.log(andMultipleExpr(true, true, false)); // should return false
console.log(andMultipleExpr(true, true, true)); // should return true

Archie
fuente
Podría reemplazar e => e === trueconBoolean
nick zoum
@nickzoum esto coincidiría con todos los valores de verdad, OP está comparando estrictamente true.
Archie
1
@ Archie - No, están comparando verdad / falsedad. No hay ===en el código del OP. Sin embargo, su everyidea es acertada . Pero solo .every(e => e)hace el trabajo.
TJ Crowder
@TJCrowder sí, acabo de notar eso. Ya se actualizó la respuesta. Gracias :)
Archie
Si agrega una función auxiliar: const isTrue = x => x === true(o x => !!xpara todos los valores de verdad), puede comprimir su solución return arguments.every(isTrue). Lo que me parece simplemente hermoso.
mbojko
9

Necesitas

  1. Comience con logicalAndestablecer entrue

  2. Úselo logicalAndal actualizarlo, en lugar de utilizar dos entradas dearguments

El cambio mínimo es:

function andMultipleExpr(){
    let logicalAnd = true; // ***
    let i;
    for (i = 0; i < arguments.length; i++){
        logicalAnd = logicalAnd && arguments[i]; // ***
    }
    return logicalAnd;
}
console.log(andMultipleExpr(true, true, false, false));

Pero la solución de mbojko tiene la ventaja de provocar un cortocircuito (detener el ciclo cuando encuentra por primera vez un valor falso), lo que parece una buena idea.

Dado que está utilizando ES2015 +, probablemente debería usar un parámetro rest en lugar de arguments, y puede usar un for-ofbucle:

function andMultipleExpr(...flags) {
    let logicalAnd = true;
    for (const flag of flags) {
        logicalAnd = logicalAnd && flag;
    }
    return logicalAnd;
}
console.log(andMultipleExpr(true, true, false, false));

También puede cortocircuitar eso de acuerdo con el enfoque de mbojko

function andMultipleExpr(...flags) {
    for (const flag of flags) {
        if (!flag) {
            return false;
        }
    }
    return true;
}
console.log(andMultipleExpr(true, true, false, false));

Algunas personas podrían lanzarse reducea esto, pero la everysolución de Archie es mucho mejor. (Pero como su comparación no es estricta, simplemente lo haría .every(flag => flag)).

T.J. Crowder
fuente
1
Gracias. Eso tiene más sentido para mí :-)
Hakim Asa
No es necesario agregar un segundo parámetro en la instrucción reduce en este caso, obtener el primer parámetro por defecto también funcionaría.
Nick Zoum
1
@nickzoum: solo si podemos suponer que la función nunca se llamará sin argumentos, ya que [].reduce((a,b)=>a && b)arroja.
TJ Crowder
6

Los retornos tempranos deberían hacer que el código sea más eficiente y más corto:

function andMultipleExpr() {
  for (let i = 0; i < arguments.length; i++) {
    if (!arguments[i]) {
      return false;
    }
  }

  return true;
}
mbojko
fuente
4

Creo que este es un camino muy corto usando ES6 Array.prototype.reduce

let andMultipleExpr = (...args) => args.reduce((a, b) => a && b);

console.log(andMultipleExpr(true, true, false, false));

Para obtener más explicaciones sobre la función de reducción, lea MDN

Patrissol Kenfack
fuente
Si usted está haciendo uso de un método de matriz, que es mucho mejor usar everycomo Archie hizo que reduce. Más simple, y cortocircuitos.
TJ Crowder
Es verdad. Pero quedémonos ahora que quiere pero LÓGICO O || ahora con la reducción, solo se cambiará && a ||
Patrissol Kenfack
O everya some. Aún más simple. Todavía cortocircuitos.
TJ Crowder
Bien hecho. Tienes razón @TJCrowder
Patrissol Kenfack
3

Puede tomar Array#everyy devolver el último valor.

Este enfoque devuelve el resultado real de AND lógico&& .

Al utilizar el enfoque, se crea un cortocircuito para el primer valor falso encontrado. Entonces la iteración se detiene.

function andMultipleExpr(...args) {
    var result; // any return value is configurable for empty args
    args.every(v => result = v);
    return result;
}

console.log(andMultipleExpr(true, true, false, false));
console.log(andMultipleExpr(true, true, 1, 2));
console.log(andMultipleExpr(true, 0, 1, 2));

Nina Scholz
fuente
3

Quizás quieras escuchar qué salió mal con el bucle:

for (i = 0; i < arguments.length; i++){
  logicalAnd =  arguments[i] && arguments[i+1];
}
  1. Este bucle almacena los &&dos últimos elementos que encuentra. En el caso ideal, reuniría &&los dos últimos elementos de la matriz (que ya no es lo que necesita)
  2. además de eso al final del ciclo i=arguments.length-1, verificará el último elemento de la matriz, y i+1es el elemento "después" del último, que es undefined. En términos de relaciones lógicas, se considera false, pero &&produce el valor en sí mismo en ese caso, y es por eso que la función regresa undefinedtodo el tiempo (esto podría haber sido mencionado en la pregunta).

Docs

expr1 && expr2: Si expr1se puede convertir a true, devuelve expr2; De lo contrario, vuelve expr1.

arr=[true];
console.log("your case:",arr[0] && arr[1]);

console.log("1 && 2:", 1 && 2);


En cambio, debe usarlo logicalAndcomo un acumulador, que recoge el resultado de &&-ing todos los elementos anteriores, y un truco que puede usar es que si el resultado de un parcial &&es false, no importa cuáles sean los elementos restantes, el resultado final va a ser falseasí que el ciclo puede detenerse de inmediato:

function andMultipleExpr(){
    let logicalAnd = arguments[0] || false;
    for (let i = 1; i < arguments.length && logicalAnd; i++){
        logicalAnd = logicalAnd && arguments[i];
    }
    return logicalAnd;
}

console.log("():",andMultipleExpr());
console.log("(false):",andMultipleExpr(false));
console.log("(true):",andMultipleExpr(true));
console.log("(true,true):",andMultipleExpr(true,true));
console.log("(true, true, false, false):",andMultipleExpr(true, true, false, false));

y luego puede optimizarlo hacia la respuesta de Archie : el resultado de &&-ing items es truesi todos los ítems son true, y no tiene que ejecutar una sola &&operación para calcular el resultado:

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

console.log("():",andMultipleExpr());
console.log("(false):",andMultipleExpr(false));
console.log("(true):",andMultipleExpr(true));
console.log("(true,true):",andMultipleExpr(true,true));
console.log("(true, true, false, false):",andMultipleExpr(true, true, false, false));

(En los fragmentos anteriores, pretendía producir falseuna lista de argumentos vacía).

Tevemadar
fuente