Умножьте все элементы в массиве JS

#javascript #arrays #calculator

#javascript #массивы #калькулятор

Вопрос:

Я новичок в JavaScript и пытаюсь разобраться в основах. Теперь я пытаюсь сделать калькулятор. Очень простой, который может складывать, вычитывать, делить и умножать. Я заставил его работать с этим кодом (отображается только умножение:

 var multiply = function () {
var numbers = prompt("How many numbers do you want to multiply?","At least 2, max 4");
        numbers = Number(numbers);
        switch (numbers){
            case 2:
                num1 = prompt("Your first number: ");
                num2 = prompt("Your second number: ");
                ans = Number(num1) * Number(num2);
                alert(num1   " * "    num2   " = "   ans);
                break;
            case 3:
                num1 = Number(prompt("Your first number: "));
                num2 = Number(prompt("Your second number: "));
                num3 = Number(prompt("Your third number: "));
                ans = Number(num1) * Number(num2) * Number(num3);
                alert(num1   " * "    num2   " * "   num3   " = "   ans);
                break;
            case 4:
                num1 = Number(prompt("Your first number: "));
                num2 = Number(prompt("Your second number: "));
                num3 = Number(prompt("Your third number: "));
                num4 = Number(prompt("Your fourth number: "));
                ans = Number(num1) * Number(num2) * Number(num3) * Number(num4);
                alert(num1   " * "    num2   " * "   num3   " * "   num4   " = "   ans);
                break;
            default:
                alert("Not valid");
                break;
        }
};
multiply();  

Моя проблема в том, что я очень ограничен, когда дело доходит до того, сколько чисел пользователь может умножить. Создание варианта переключения для каждого возможного количества займет некоторое время, поэтому я подумал об этом:

     var multiply = function () {
        var numbers = [];
        var ans = 0;
        var times = prompt("How many numbers do you want to multiply?");
        for(var i = 0; i<times; i  ){
            Number(numbers.push(prompt("Please, enter one of your numbers")));
        }
        alert(ans);
    };
    multiply();  

Итак, мой вопрос: как я могу заставить «ans» быть равным каждому элементу моего массива «numbers», умноженному друг на друга?

Ответ №1:

Вы можете использовать функцию уменьшения:

 [1, 2, 3, 4].reduce(function(a, b) {
  return a * b;
}); // it return 24
  

Кстати. в вашем цикле вы должны нажимать на массив таким образом:

 for(var i = 0; i<times; i  ){
  numbers.push(Number(prompt("Please, enter one of your numbers")));
}
  

Ответ №2:

Как указано в других ответах, вы можете использовать Array.reduce метод. Но вместо того, чтобы запускать собственную функцию умножения, вы также можете использовать собственный Math.imul метод:

 var numbers = [1, 2, 3, 4];
var ans = numbers.reduce(Math.imul);

console.log(ans);  

Комментарии:

1. Math.imul из ES6 и, похоже, обладает некоторыми странными свойствами. (a,b)=>a*b на 1 символ длиннее.

2. @4castle уже есть другие ответы, показывающие функциональное решение (без жирной стрелки), и поскольку OP является новым, я пытался осветить для них другие области JavaScript с соответствующими ссылками, которые подробно описывают, что и как работают эти функции. Не нужно зацикливаться на альтернативных решениях или вступать в войну за количество символов (2 пробела против 4 пробелов и т.д.). 🙂

Ответ №3:

Если я вас правильно понял, вы хотите что-то вроде multiply([1, 2, 3, 4]) === 24 ? Затем вы можете использовать https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

Комментарии:

1. Спасибо! Вы правильно поняли, и ваш метод сработал! Спасибо 🙂

Ответ №4:

Вы могли бы просто продолжать запрашивать число и одновременно показывать промежуточный результат. Пользователь может завершить работу с помощью escape:

 var multiply = function () {
  var s, ans = 1;
  while (s = prompt('Current product is '   ans   
                    '. Enter next factor to multiply with, or hit escape to exit')) {
    ans *= Number(s);
  }
}
multiply();  

Ответ №5:

Уменьшить, вероятно, правильный ответ, но чтобы дать вам более полное представление о том, что он на самом деле делает, взгляните на это. Вот как я бы вручную сделал в основном то же самое, добавив несколько защитных элементов, чтобы сделать это более безопасным.

 //This is an enum. It's basically a cleaner and more
//scalable way to define constants. Here I'm using an
//integer to represent each of the four operations
var OPERATIONS = {
  'ADD': 1,
  'SUBTRACT': 2,
  'MULTIPLY': 3,
  'DIVIDE': 4
};

function calc (operation, values)
{
  if (!operation || !values || values.length < 2)
  {
    //The inputs aren't valid, so throw some kind of error
  }

  //This will be used in all of our cases, so
  //we define it at a larger scope
  var resu<

  switch (operation)
  {
    case OPERATIONS.MULTIPLY:
      //Extracts the first value and stores it
      result = values.shift ();

      //Iterate through the remaining values.
      //Remember that the first value is no
      //longer in the set
      values.forEach (function (value, index)
      {
        //*= is a unary operator which multiplies a value by
        //the operand, and then stores it back in itself.
        //This is equivalent to result = result * value.
        result *= value;
      });

      break;
    //Create cases for ADD, SUBTRACT, and DIVIDE
  }

  return resu<
}

//Test cases
console.log (calc (OPERATIONS.ADD, [1, 1]); //Prints 2
console.log (calc (OPERATIONS.SUBTRACT, [10, 1, 1]); //Prints 8
console.log (calc (OPERATIONS.MULTIPLY, [1, 2, 3, 4]); //Prints 24
console.log (calc (OPERATIONS.ADD, [calc (OPERATIONS.MULTIPLY, [5, 5], 3, 100]); //Prints 128
  

Вы можете сделать это немного более обобщенным, если хотите сделать что-то подобное…

 function calc2 (operations, values)
{
  //You need one more value than operation here
  if (!operations || !values || values.length < 2 || (values.length - operations.length !== 1))
  {
    //The inputs aren't valid, so throw some kind of error
  }

  var result = values.shift ();

  while (values.length)
  {
    switch (operations[0])
    {
      case OPERATIONS.ADD:
        result  = values[0]

        break;
      case OPERATIONS.SUBTRACT:
        result -= values[0]

        break;
      case OPERATIONS.MULTIPLY:
        result *= values[0]

        break;
      case OPERATIONS.DIVIDE:
        result /= values[0]

        break;
      default:
        //Something has gone horribly wrong. Thrown an error
    }

    //Work your way down the array by continually
    //removing the first value
    values.shift ();
    operations.shift ();
  }

  //Note that this method solves the equation linerally;
  //BEDMAS (or PEMDAS, depending on where you're from)
  //is not honoured.
  return resu<
}

//Test cases
console.log (calc ([OPERATIONS.ADD], [1, 1])); //Prints 2
console.log (calc ([OPERATIONS.ADD, OPERATIONS.ADD], [1, 2, 3])); //Prints 6
console.log (calc ([OPERATIONS.ADD, OPERATIONS.ADD, OPERATIONS.DIVIDE], [6, 7, 5, 3])); //Prints 6
  

Эта вторая функция будет использоваться путем хранения входных данных и операций по одному. Таким образом, вы получаете что-то вроде 6 7 5 / 3 = , а затем разбиваете это на отдельные компоненты для выполнения вычисления.

Общая методология здесь заключается в том, что вы хотите получить базовое значение, а затем выполнить итерацию поверх него, чтобы получить конечный результат. В первом случае это означает изменение значения с помощью одной и той же операции для каждого значения. Во втором случае вы указываете ему тип мутации, которую вы хотели бы выполнять на каждом шаге, а не в начале.

Если вы хотите обобщить это на используемые BEDMAS или иметь более сложную функциональность, вам, вероятно, придется создать древовидную структуру, где каждый узел представляет операцию и соответствующие ей операнды, и чтобы получить свой результат, вы просто пройдетесь по дереву.

например PLUS(PLUS(DIVIDE(5, 3), 7), 6)