E vários 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));

O que eu estou esperando é executar este código: true && true && false && false e isso deve retornar false .

Como fazer isso funcionar em js? obrigado


Estou apenas hesitando. Quero ter certeza se minha ideia está bem formulada. Se houver uma maneira melhor, por favor sugira.
— Hakim Asa

Qual deve ser a saída quando os valores de Troothy são usados ​​em vez de booleanos? ou seja, andMultipleExpr(1, 1, 0, 0)ouandMultipleExpr(1, 1, 1, 1)
— nick Zoum

Além disso, qual deve ser a saída de andMultipleExpr()(Chamando a função sem parâmetros)?
— nick zoum 15/01

bem, esses casos também precisam ser levados em consideração. :-)
— Hakim Asa

Respostas:


16

Use Array.prototype.everyem todos os argumentos passados ​​para verificar se todos são verdadeiros;

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


Pode substituir e => e === trueporBoolean
— nick zoum 15/01

@nickzoum isso corresponderia a todos os valores de verdade, o OP está comparando estritamente true.
— Archie

11
@ Archie - Não, eles estão comparando verdade / falsidade. Não existe ===no código do OP. Sua everyideia é certa , no entanto. Mas apenas .every(e => e)faz o trabalho.
— TJ Crowder

@TJCrowder sim, notei isso. Atualizada a resposta já. Obrigado :)
— Archie

Se você adicionar uma função auxiliar: const isTrue = x => x === true(ou x => !!xpara todos os valores reais), poderá compactar sua solução return arguments.every(isTrue). O que para mim parece bonito.
— mbojko 15/01

9

Você precisa

  1. Comece com logicalAnddefinido comotrue

  2. Use logicalAndao atualizá-lo, em vez de usar duas entradas dearguments

A mudança mínima é:

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));

Mas a solução da mbojko tem a vantagem de causar um curto-circuito (interromper o ciclo quando encontrar um valor falso), o que parece uma boa ideia.

Como você está usando o ES2015 +, você provavelmente deve usar um parâmetro rest em vez de argumentse pode usar um for-ofloop:

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

Você também pode causar um curto-circuito, de acordo com a abordagem da mbojko

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

Algumas pessoas podem pensar reducenisso, mas a everysolução de Archie é muito melhor. (Mas, como sua comparação não é rigorosa, é só fazê-lo .every(flag => flag).)


11
Obrigado. Isso faz mais sentido para mim :-)
— Hakim Asa

Não há necessidade de adicionar um segundo parâmetro na instrução de redução nesse caso, obter o primeiro parâmetro por padrão também funcionaria.
— nick zoum 15/01

11
@nickzoum - Somente se pudermos assumir que a função nunca será chamada sem argumentos, pois [].reduce((a,b)=>a && b)lança.
— TJ Crowder

6

Os retornos antecipados devem tornar o código mais eficiente e mais curto:

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

  return true;
}

4

Eu acho que essa é uma maneira muito curta de usar o ES6 Array.prototype.reduce

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

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

Para mais explicações sobre a função de redução, leia MDN


Se você estiver usando um método de matriz, é muito melhor usar everycomo o Archie do que reduce. Mais simples, e curto-circuitos.
— TJ Crowder

É verdade. Mas vamos ficar agora que ele quer, mas LÓGICO OU || agora com a redução, será apenas mudar && para ||
— Patrissol Kenfack 15/01

Ou everypara some. Ainda mais simples. Ainda curto-circuito.
— TJ Crowder

Bem feito. Você está certo @TJCrowder
— Patrissol Kenfack

3

Você pode pegar Array#everye retornar o último valor.

Essa abordagem retorna o resultado real do AND lógico&& .

Usando a abordagem, é feito um curto-circuito para o primeiro valor encontrado de falsidade. Então a iteração pára.

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));


3

Talvez você queira ouvir o que deu errado com o loop:

for (i = 0; i < arguments.length; i++){
  logicalAnd =  arguments[i] && arguments[i+1];
}
  1. esse loop armazena os &&dois últimos itens que encontra. No caso ideal, reuniria &&os dois últimos elementos da matriz (que já não é o que você precisa)
  2. além disso, no final do loop i=arguments.length-1, ele verifica o último elemento da matriz e i+1é o elemento "depois" do último, que é undefined. Em termos de relações lógicas, é considerado false, mas &&produz o valor em si mesmo, e é por isso que a função retorna undefinedo tempo todo (isso poderia ter sido mencionado na pergunta).

Documentos

expr1 && expr2: Se expr1pode ser convertido em true, retorna expr2; mais, retorna expr1.

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

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


Em vez disso, você deve usar logicalAndcomo um acumulador, que coleta o resultado de &&todos os elementos anteriores, e um truque que você pode usar é se o resultado de uma parcial &&for false, não importa quais são os elementos restantes, o resultado final vai ser false, então o loop pode parar imediatamente:

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));

e, em seguida, você pode otimizá-lo para a resposta de Archie : o resultado de &&itens -ing é truese todos os itens forem truee você não precisa executar uma única &&operação para calcular o 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));

(Nos trechos acima, pretendi produzir falsepara uma lista de argumentos vazia.)

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.