И несколько параметров


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

Я ожидаю выполнения этого кода: true && true && false && false, и это должно вернуть false .

Как заставить это работать в JS? Спасибо


Я просто колеблюсь. Я хочу быть уверен, что моя идея хорошо сформулирована. Если есть лучший способ, пожалуйста, предложите.
— Хаким Аса

Каким должен быть вывод, когда вместо логических значений используются значения Troothy? то есть andMultipleExpr(1, 1, 0, 0)илиandMultipleExpr(1, 1, 1, 1)
— Ник Зоум

Кроме того, что должно быть на выходе andMultipleExpr()(вызов функции без параметров)?
— Ник Зум

ну, эти случаи также должны быть приняты во внимание. :-)
— Хаким Аса

Ответы:


16

Используйте Array.prototype.everyвсе переданные аргументы, чтобы проверить, все ли они истинны;

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


Может заменить e => e === trueнаBoolean
— Ник Зоум

@nickzoum это будет соответствовать всем истинным значениям, OP строго сравнивает true.
— Арчи

1
@ Арчи - Нет, они сравнивают правду и ложь. Там нет ===в коде ОП. Ваша everyидея , однако, на месте . Но просто .every(e => e)делает свою работу.
— TJ Crowder

@TJCrowder да только что заметил это. Обновил ответ уже. Спасибо :)
— Арчи

Если вы добавите вспомогательную функцию: const isTrue = x => x === true(или x => !!xдля всех истинных значений), вы можете сжать свое решение в return arguments.every(isTrue). Который мне кажется просто красивым.
— Мбойко

9

Тебе следует

  1. Начните с logicalAndнабораtrue

  2. Использовать logicalAndпри обновлении, а не использовать две записи изarguments

Минимальное изменение:

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

Но у решения mbojko есть преимущество короткого замыкания (остановка цикла, когда он впервые находит ложное значение), что кажется хорошей идеей.

Поскольку вы используете ES2015 +, вам, вероятно, следует использовать параметр rest, а не arguments, и вы можете использовать for-ofцикл:

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

Вы также можете замкнуть, что в соответствии с подходом Мбойко

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

Некоторые люди могут бросить reduceэто, но решение Арчиevery намного лучше. (Но поскольку ваше сравнение не является строгим, я бы просто сделал это .every(flag => flag).)


1
Спасибо. Это имеет больше смысла для меня :-)
— Хаким Аса

В этом случае нет необходимости добавлять второй параметр в оператор Redu, получение первого параметра по умолчанию также будет работать.
— Ник Зоум

1
@nickzoum - Только если мы можем предположить, что функция никогда не будет вызываться без аргументов, так как [].reduce((a,b)=>a && b)throws.
— TJ Crowder

6

Ранний возврат должен сделать код более эффективным и более коротким:

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

  return true;
}

4

Я думаю, что это очень короткий путь с использованием ES6 Array.prototype.reduce

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

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

Для получения более подробной информации о функции снижения, пожалуйста, прочитайте MDN


Если вы делаете , чтобы использовать метод массива, это гораздо лучше использовать , everyкак Арчи сделал чем reduce. Проще, и это короткие замыкания.
— TJ Crowder

Это правда. Но давайте останемся сейчас, он хочет, но ЛОГИЧЕСКОЕ ИЛИ || теперь с уменьшением, это будет просто изменить && на ||
— Патриссол Кенфак

Или everyк some. Все еще проще. Все еще короткие замыкания.
— TJ Crowder

Отлично сработано. Ты прав @TJCrowder
— Патриссол Кенфак

3

Вы можете взять Array#everyи вернуть последнее значение.

Такой подход возвращает реальный результат логического И&& .

Используя этот подход, создается короткое замыкание для первого найденного ложного значения. Затем итерация останавливается.

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

Возможно, вы хотите услышать, что пошло не так с циклом:

for (i = 0; i < arguments.length; i++){
  logicalAnd =  arguments[i] && arguments[i+1];
}
  1. этот цикл хранит &&последние два элемента, с которыми он сталкивается. В идеальном случае это были бы &&вместе два последних элемента массива (что уже не то, что вам нужно)
  2. Кроме того, в конце цикла i=arguments.length-1он проверяет последний элемент массива и i+1является элементом «после» последнего, то есть undefined. С точки зрения логических отношений это рассматривается false, но в этом случае &&создает само значение, и поэтому функция возвращает undefinedвсе время (это можно было упомянуть в вопросе).

Документы

expr1 && expr2: Если expr1можно преобразовать в true, возвращает expr2; еще, возвращается expr1.

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

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


Вместо этого, вы должны использовать в logicalAndкачестве аккумулятора, который собирает результат &&-ную все предыдущие элементы, и хитрость , что вы можете использовать, если в результате частичного &&является false, это не имеет значения , что остальные элементы, конечный результат будет false, поэтому цикл может немедленно остановиться:

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

и затем вы можете оптимизировать его в соответствии с ответом Арчи : результат &&-ing элементов - это trueесли все элементы есть true, и вам не нужно выполнять одну &&операцию для вычисления результата:

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

(В приведенных выше фрагментах я стремился falseсоздать пустой список аргументов.)

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.