UND mehrere Parameter

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

Was ich erwarte, ist, diesen Code auszuführen: true && true && false && false und das sollte false zurückgeben .

Wie macht man das in js? Vielen Dank

Hakim Asa
quelle
Ich zögere nur. Ich möchte sicher sein, ob meine Idee gut formuliert ist. Wenn es einen besseren Weg gibt, schlagen Sie bitte vor.
Hakim Asa
Was sollte ausgegeben werden, wenn Troothy-Werte anstelle von Booleschen Werten verwendet werden? dh andMultipleExpr(1, 1, 0, 0)oderandMultipleExpr(1, 1, 1, 1)
nick zoum
Was soll auch ausgegeben werden andMultipleExpr()(Aufruf der Funktion ohne Parameter)?
Nick Zoum
Nun, diese Fälle müssen ebenfalls berücksichtigt werden. :-)
Hakim Asa

Antworten:

16

Verwenden Sie Array.prototype.everyfür alle übergebenen Argumente, um zu überprüfen, ob sie alle wahr sind.

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
quelle
Könnte ersetzen e => e === truemitBoolean
nick Zoum
@nickzoum dies würde allen wahrheitsgemäßen Werten entsprechen, OP vergleicht streng true.
Archie
1
@Archie - Nein, sie vergleichen Wahrheit / Falschheit. Es gibt keine ===im OP-Code. Ihre everyIdee ist jedoch genau richtig. Aber macht einfach .every(e => e)den Job.
TJ Crowder
@TJCrowder hat das ja gerade bemerkt. Die Antwort wurde bereits aktualisiert. Danke :)
Archie
Wenn Sie eine Hilfsfunktion hinzufügen: const isTrue = x => x === true(oder x => !!xfür alle wahrheitsgemäßen Werte), können Sie Ihre Lösung in komprimieren return arguments.every(isTrue). Was mir einfach wunderschön erscheint.
mbojko
9

Du brauchst

  1. Beginnen Sie mit logicalAndset totrue

  2. Verwenden Sie diese logicalAndOption, wenn Sie sie aktualisieren, anstatt zwei Einträge aus zu verwendenarguments

Die minimale Änderung ist:

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

Aber mbojko Lösung hat den Vorteil eines Kurzschlusses (Anhalten der Schleife , wenn es zuerst einen falsy Wert findet), die wie eine gute Idee zu sein scheint.

Da Sie ES2015 + verwenden, sollten Sie wahrscheinlich einen Rest-Parameter anstelle von verwenden arguments, und Sie können eine for-ofSchleife verwenden:

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

Sie können dies auch im Einklang mit dem Ansatz von mbojko kurzschließen

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

Einige Leute mögen darauf werfen reduce, aber Archies everyLösung ist viel besser. (Aber da Ihr Vergleich nicht streng ist, würde ich es einfach machen .every(flag => flag).)

T.J. Crowder
quelle
1
Vielen Dank. Das macht für mich mehr Sinn :-)
Hakim Asa
In diesem Fall muss der redu-Anweisung kein zweiter Parameter hinzugefügt werden. Standardmäßig funktioniert es auch, den ersten Parameter zu erhalten.
Nick Zoum
1
@nickzoum - Nur wenn wir davon ausgehen können, dass die Funktion seit [].reduce((a,b)=>a && b)Würfen niemals ohne Argumente aufgerufen wird .
TJ Crowder
6

Frühe Rückgaben sollten den Code sowohl effizienter als auch kürzer machen:

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

  return true;
}
mbojko
quelle
4

Ich denke, dies ist ein sehr kurzer Weg mit ES6 Array.prototype.reduce

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

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

Weitere Erläuterungen zur Reduzierungsfunktion finden Sie unter MDN

Patrissol Kenfack
quelle
Wenn Sie eine Array-Methode verwenden, ist es viel besser, sie everywie Archie zu verwenden als reduce. Einfacher und es schließt kurz.
TJ Crowder
Es ist wahr. Aber lass uns jetzt bleiben, er will nur LOGISCH ODER || Jetzt mit dem Reduzieren wird es nur && auf ||
Patrissol Kenfack
Oder everyzu some. Noch einfacher. Immer noch Kurzschlüsse.
TJ Crowder
Gut gemacht. Sie haben Recht @TJCrowder
Patrissol Kenfack
3

Sie können Array#everyden letzten Wert annehmen und zurückgeben.

Dieser Ansatz gibt das tatsächliche Ergebnis des logischen UND zurück&& .

Unter Verwendung des Ansatzes wird ein Kurzschluss für den zuerst gefundenen falschen Wert hergestellt. Dann stoppt die Iteration.

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
quelle
3

Vielleicht möchten Sie hören, was mit der Schleife schief gelaufen ist:

for (i = 0; i < arguments.length; i++){
  logicalAnd =  arguments[i] && arguments[i+1];
}
  1. Diese Schleife speichert die &&letzten beiden Elemente, auf die sie stößt. Im Idealfall würden &&die letzten beiden Elemente des Arrays zusammengefügt (was bereits nicht das ist, was Sie brauchen).
  2. Darüber hinaus i=arguments.length-1überprüft es am Ende der Schleife das letzte Element des Arrays und i+1ist das Element "nach" dem letzten Element, das ist undefined. In Bezug auf logische Beziehungen wird es berücksichtigt false, &&erzeugt aber in einem solchen Fall den Wert selbst, und deshalb gibt die Funktion die undefinedganze Zeit zurück (dies hätte in der Frage erwähnt werden können).

Docs

expr1 && expr2: Wenn expr1konvertiert werden kann, truewird zurückgegeben expr2; sonst kehrt zurück expr1.

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

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


Stattdessen sollten Sie logicalAndals Akkumulator verwenden, der das Ergebnis &&aller vorherigen Elemente sammelt. Ein Trick, den Sie verwenden können, ist, wenn das Ergebnis eines Teils &&ist false, spielt es keine Rolle, was die verbleibenden Elemente sind, das Endergebnis wird sein false, so dass die Schleife sofort anhalten kann:

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

und dann können Sie es in Richtung Archies Antwort optimieren : Das Ergebnis von &&-ing Elementen ist, truewenn alle Elemente vorhanden sind true, und Sie müssen keine einzige &&Operation ausführen, um das Ergebnis zu berechnen:

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

(In den obigen Ausschnitten wollte ich falseeine leere Argumentliste erstellen.)

tevemadar
quelle