ET plusieurs paramètres

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

Ce que j'attends, c'est d'exécuter ce code: true && true && false && false et cela devrait retourner false .

Comment faire fonctionner ça en js? Merci

Hakim Asa
la source
J'hésite juste. Je veux être sûr que mon idée est bien formulée. S'il existe une meilleure solution, veuillez suggérer.
Hakim Asa
Quelle devrait être la sortie lorsque les valeurs Troothy sont utilisées à la place des booléens? soit andMultipleExpr(1, 1, 0, 0)ouandMultipleExpr(1, 1, 1, 1)
nick zoum
De plus, quelle devrait être la sortie de andMultipleExpr()(Appel de la fonction sans paramètres)?
nick zoum le
eh bien, ces cas doivent également être pris en compte. :-)
Hakim Asa

Réponses:

16

Utilisez Array.prototype.everytous les arguments passés pour vérifier s'ils sont tous vrais;

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
la source
Pourrait remplacer e => e === trueparBoolean
Nick Zoum
@nickzoum, cela correspondrait à toutes les valeurs véridiques, OP compare strictement true.
Archie
1
@Archie - Non, ils comparent vérité / fausse. Il n'y a pas ===dans le code OP. Mais votre everyidée est parfaite . Mais fait juste .every(e => e)le travail.
TJ Crowder
@TJCrowder oui vient de le remarquer. Déjà mis à jour la réponse. Merci :)
Archie
Si vous ajoutez une fonction d'assistance: const isTrue = x => x === true(ou x => !!xpour toutes les valeurs véridiques), vous pouvez compresser votre solution dans return arguments.every(isTrue). Ce qui me semble tout simplement magnifique.
mbojko
9

Tu dois

  1. Commencez par logicalAnddéfinir surtrue

  2. À utiliser logicalAndlors de la mise à jour, plutôt que d'utiliser deux entrées dearguments

Le changement minimal est:

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

Mais la solution de mbojko a l'avantage de court-circuiter (arrêter la boucle lorsqu'elle trouve une valeur falsifiée pour la première fois), ce qui semble être une bonne idée.

Puisque vous utilisez ES2015 +, vous devriez probablement utiliser un paramètre de repos plutôt que arguments, et vous pouvez utiliser une for-ofboucle:

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

Vous pouvez également court-circuiter cela conformément à l'approche de mbojko

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

Certaines personnes pourraient y jeter un coup reduced'œil, mais la everysolution d'Archie est bien meilleure. (Mais comme votre comparaison n'est pas stricte, je le ferais .every(flag => flag).)

T.J. Crowder
la source
1
Merci. Cela a plus de sens pour moi :-)
Hakim Asa
Il n'est pas nécessaire d'ajouter un second paramètre dans l'instruction de réduction dans ce cas, obtenir le premier paramètre par défaut fonctionnerait également.
nick zoum le
1
@nickzoum - Seulement si nous pouvons supposer que la fonction ne sera jamais appelée sans arguments, car [].reduce((a,b)=>a && b)throws.
TJ Crowder
6

Les retours anticipés devraient rendre le code à la fois plus efficace et plus court:

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

  return true;
}
mbojko
la source
4

Je pense que c'est un moyen très court d' utiliser ES6 Array.prototype.reduce

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

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

Pour plus d'explications sur la fonction de réduction, veuillez lire MDN

Patrissol Kenfack
la source
Si vous faites d'utiliser une méthode de tableau, il est bien préférable d'utiliser everycomme Archie a fait que reduce. Plus simple, et ça court-circuite.
TJ Crowder
C'est vrai. Mais restons maintenant, il veut mais OU LOGIQUE || maintenant avec la réduction, ce sera juste changer && à ||
Patrissol Kenfack
Ou everypour some. Encore plus simple. Toujours des courts-circuits.
TJ Crowder
Bien joué. Vous avez raison @TJCrowder
Patrissol Kenfack
3

Vous pouvez prendre Array#everyet renvoyer la dernière valeur.

Cette approche renvoie le résultat réel d'un ET logique&& .

En utilisant l'approche, un court-circuit est effectué pour la première valeur de falsification trouvée. Ensuite, l'itération s'arrête.

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
la source
3

Peut-être que vous voulez entendre ce qui a mal tourné avec la boucle:

for (i = 0; i < arguments.length; i++){
  logicalAnd =  arguments[i] && arguments[i+1];
}
  1. cette boucle stocke les &&deux derniers éléments rencontrés. Dans le cas idéal, il &&regrouperait les deux derniers éléments du tableau (ce qui n'est déjà pas ce dont vous avez besoin)
  2. en plus de cela à la fin de la boucle i=arguments.length-1, il vérifiera le dernier élément du tableau, et i+1est l'élément "après" le dernier, qui est undefined. En termes de relations logiques, il est considéré false, mais &&produit la valeur elle-même dans ce cas, et c'est pourquoi la fonction revient undefinedtout le temps (cela aurait pu être mentionné que dans la question).

Documents

expr1 && expr2: Si expr1peut être converti en true, retourne expr2; sinon, revient expr1.

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

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


Au lieu de cela, vous devez utiliser logicalAndcomme accumulateur, qui recueille le résultat de &&-ing tous les éléments précédents, et une astuce que vous pouvez utiliser est que si le résultat d'un partiel &&est false, peu importe ce que sont les éléments restants, le résultat final va être false, donc la boucle peut s'arrêter immédiatement:

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

et ensuite vous pouvez l'optimiser vers la réponse d'Archie : le résultat des &&éléments -ing est truesi tous les éléments le sont true, et vous n'avez pas à exécuter une seule &&opération pour calculer le résultat:

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

(Dans les extraits ci-dessus, je visais à produire falseune liste d'arguments vide.)

tevemadar
la source