I wiele parametrów

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

Oczekuję wykonania tego kodu: true i& true i& false i& false, a to powinno zwrócić false .

Jak to zrobić w js? Dzięki

Hakim Asa
źródło
Waham się. Chcę się upewnić, czy mój pomysł jest dobrze sformułowany. Jeśli istnieje lepszy sposób, proszę zasugerować.
Hakim Asa
Jaka powinna być wartość wyjściowa, gdy zamiast wartości logicznych stosowane są wartości Troothy? tj. andMultipleExpr(1, 1, 0, 0)lubandMultipleExpr(1, 1, 1, 1)
nick zoum
A także, co powinno być wyjściem andMultipleExpr()(Wywołanie funkcji bez parametrów)?
nick zoum
Cóż, te przypadki również należy wziąć pod uwagę. :-)
Hakim Asa

Odpowiedzi:

16

Użyj Array.prototype.everywszystkich przekazanych argumentów, aby sprawdzić, czy wszystkie są prawdziwe;

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
źródło
Mogą zastąpić e => e === truezBoolean
NICK zoum
@nickzoum to pasowałoby do wszystkich prawdziwych wartości, OP jest ściśle porównywane true.
Archie
1
@Archie - Nie, porównują prawdę / fałsz. Nie ma ===w kodzie OP. Twój everypomysł jest jednak na miejscu . Ale po prostu .every(e => e)działa.
TJ Crowder
@TJCrowder tak właśnie to zauważyłem. Zaktualizowałem już odpowiedź. Dzięki :)
Archie
Jeśli dodasz funkcję pomocnika: const isTrue = x => x === true(lub x => !!xdla wszystkich prawdziwych wartości), możesz skompresować swoje rozwiązanie return arguments.every(isTrue). Co wydaje mi się po prostu piękne.
mbojko
9

Musisz

  1. Zacznij od logicalAndustawienia natrue

  2. Użyj logicalAndpodczas aktualizacji, zamiast używać dwóch wpisów zarguments

Minimalna zmiana to:

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

Ale rozwiązanie mbojko ma tę zaletę, że powoduje zwarcie (zatrzymanie pętli, gdy po raz pierwszy znajdzie wartość fałsz), co wydaje się dobrym pomysłem.

Ponieważ używasz ES2015 +, prawdopodobnie powinieneś raczej użyć parametru rest argumentsi możesz użyć for-ofpętli:

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

Możesz także zewrzeć to zgodnie z podejściem mbojko

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

Niektórzy mogą reducena to rzucić , ale rozwiązanie Archiegoevery jest znacznie lepsze. (Ale ponieważ twoje porównanie nie jest ścisłe, po prostu to zrobię .every(flag => flag).)

T.J. Crowder
źródło
1
Dzięki. To ma dla mnie więcej sensu :-)
Hakim Asa
W tym przypadku nie ma potrzeby dodawania drugiego parametru do instrukcji redukowania, domyślnie uzyskanie pierwszego parametru również działałoby.
nick zoum
1
@nickzoum - Tylko jeśli możemy założyć, że funkcja nigdy nie zostanie wywołana bez argumentów, ponieważ [].reduce((a,b)=>a && b)wyrzuca.
TJ Crowder
6

Wczesne zwroty powinny uczynić kod zarówno bardziej wydajnym, jak i krótszym:

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

  return true;
}
mbojko
źródło
4

Myślę, że jest to bardzo krótka droga z użyciem ES6 Array.prototype.reduce

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

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

Aby uzyskać więcej informacji na temat funkcji zmniejszania, przeczytaj MDN

Patrissol Kenfack
źródło
Jeśli robisz użyć metody array, to dużo lepiej używać everyjak Archie zrobił niż reduce. Prostsze i powoduje zwarcie.
TJ Crowder
To prawda. Ale zostańmy teraz, jak on chce, ale LOGICZNY LUB || teraz z redukcją, będzie to po prostu zmiana && na ||
Patrissol Kenfack
Lub everydo some. Wciąż prostsze. Nadal występują zwarcia.
TJ Crowder
Dobra robota. Masz rację @TJCrowder
Patrissol Kenfack
3

Możesz wziąć Array#everyi zwrócić ostatnią wartość.

To podejście zwraca prawdziwy wynik logicznego AND&& .

Przy zastosowaniu tego podejścia następuje zwarcie dla pierwszej znalezionej wartości falsy. Następnie iteracja się kończy.

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
źródło
3

Być może chcesz usłyszeć, co poszło nie tak z pętlą:

for (i = 0; i < arguments.length; i++){
  logicalAnd =  arguments[i] && arguments[i+1];
}
  1. ta pętla przechowuje &&dwa ostatnie napotkane elementy. W idealnym przypadku byłyby &&to dwa ostatnie elementy tablicy (co już nie jest tym, czego potrzebujesz)
  2. na końcu na końcu pętli i=arguments.length-1sprawdzi ostatni element tablicy i i+1będzie to element „po” ostatniego, czyli undefined. Pod względem relacji logicznych jest to rozważane false, ale&& w takim przypadku sama wytwarza wartość, i dlatego funkcja zwraca undefinedcały czas (można o tym wspomnieć w pytaniu).

Dokumenty

expr1 && expr2: Jeśli expr1można przekonwertować na true, zwraca expr2; w przeciwnym razie zwraca expr1.

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

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


Zamiast tego powinieneś użyć logicalAndjako akumulatora, który zbiera wynik &&-stosowania wszystkich poprzednich elementów, a sztuczką, którą możesz zastosować, jest to, że jeśli wynikiem częściowego &&jest false, nie ma znaczenia, jakie są pozostałe elementy, wynik końcowy będzie false, więc pętla może się natychmiast zatrzymać:

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

a następnie możesz zoptymalizować go w kierunku odpowiedzi Archiego : wynikiem &&-ing elementów jest, truejeśli wszystkie są true, i nie musisz wykonywać żadnej &&operacji w celu obliczenia wyniku:

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

(W powyższych fragmentach chciałem falsestworzyć pustą listę argumentów.)

tevemadar
źródło