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


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


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


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

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


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


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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.