Алгоритмы JavaScript: Mini-Max Sum
Для сегодняшнего алгоритма мы собираемся создать функцию с именем miniMaxSum. В этой функции вам предоставляется массив из пяти целых чисел, и цель состоит в том, чтобы вывести минимальное и максимальное значения, которые можно рассчитать при суммировании четырех из пяти целых чисел в массиве.
Вот пример. Давайте создадим массив с именем arr
:
let arr = [1, 2, 3, 4, 5]
Если бы мы визуально прошли цикл по массиву, мы суммировали бы оставшиеся четыре числа, исключая число, в котором находится цикл.
Цикл доходит до первого числа, мы исключаем число 1 и суммируем оставшиеся четыре числа: 2 + 3 + 4 + 5 = 14.
Цикл доходит до второго числа, мы исключаем число 2 и суммируем оставшиеся четыре числа: 1 + 3 + 4 + 5 = 13.
Цикл доходит до третьего числа, мы исключаем число 3 и суммируем оставшиеся четыре числа: 1 + 2 + 4 + 5 = 12.
Цикл доходит до четвертого числа, мы исключаем число 4 и суммируем оставшиеся четыре числа: 1 + 2 + 3 + 5 = 11.
Цикл дойдет до последнего числа, мы исключим число 5 и сложим оставшиеся четыре числа: 1 + 2 + 3 + 4 = 10.
Из всех сумм 14 - это максимум, а 10 - это наш минимум, поэтому наша функция выведет эти два числа в одну строку, разделенную пробелом:
10 14
Теперь мы закончили с нашим длинным объяснением, давайте превратим его в код.
Мы создаем наши переменные:
let totals = [];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
Переменная totals
будет собирать все наши суммы и поместит каждую сумму в массиве.
Переменную reducer
мы объясним позже. Это будет включать использование метода Array.reduce() для добавления четырех чисел, чтобы получить нашу сумму.
Сначала мы перебираем наш массив с помощью цикла for:
for (let i = 0; i < arr.length; i++) {
let filtered = arr.filter(function(value, index, arr) {
return i !== index;
});
totals.push(filtered.reduce(reducer));
}
В первой строке нашего блока for-loop мы будем использовать метод .filter()
, чтобы избавиться от определенных значений в массиве. Метод фильтра использует метод обратного вызова (функция, выполняющая другую функцию после его завершения), и, когда метод фильтра выполняет итерацию по каждому элементу массива, он передаст обратному вызову три значения: текущее значение, индекс массива и сам массив. Когда это будет сделано итерацией по этому конкретному значению массива, обратный вызов вернет либо истину, либо ложь на основе вашего оператора возврата. Значения, которые возвращают true
, добавляются в фильтруемый массив.
Когда мы перебираем массив, мы хотим вычислить все элементы в массиве, кроме текущего итерированного значения.
Мы используем метод filter
для фильтрации значения, равного текущему элементу, индексируемому в цикле for. Например, если цикл for в данный момент находится на втором числе, мы хотим, чтобы метод filter отфильтровывал все числа, которые не имеют индекса 1.
Метод фильтра не касается и не изменяет исходный массив. Это важно, поэтому у нас всегда есть исходный массив для фильтрации на протяжении цикла for.
Следующая строка:
totals.push(filtered.reduce(reducer));
После того, как метод фильтра выведет наш массив из четырех значений, мы добавим их вместе, используя метод Reduce.
Метод Reduce выполняет функцию для каждого элемента массива. Это уменьшает наш массив до одного значения. Давайте вернемся к тому, где мы перечислили наши переменные, и объясним, что делает наша переменная reducer
:
const reducer = (accumulator, currentValue) => accumulator + currentValue;
И заметьте, приведенное выше утверждение эквивалентно написанию:
const reducer = function(accumulator, currentValue){
return accumulator + currentValue;
}
Верхняя часть использует функции стрелок, которые являются другим способом (и сокращенным способом) для написания функции.
Метод Reduce принимает один обязательный параметр - редуктор. Наша функция reducer
принимает два параметра: аккумулятор и текущее значение. Метод Reduction также имеет необязательный параметр initialValue, но мы его опускаем. Аккумулятор будет равен первому значению в массиве, а значение currentValue будет равно второму.
Возвращаясь к нашему примеру вверху с [1, 2, 3, 4, 5], мы увидим связь между currentValue и аккумулятором:
// 2 текущее значение. значение аккумулятора, обновленное до 3
1 + 2 = 3
// 3, является текущим значением. значение аккумулятора обновлено до 6
3 + 3 = 6
// 4 - текущее значение. значение аккумулятора обновлено до 10
6 + 4 = 10
// ... и т.д.
Каждый раз, когда текущее значение добавляется в аккумулятор, аккумулятор обновляется до тех пор, пока массив не будет завершен и не будет возвращено окончательное значение аккумулятора.
Возвращаясь к циклу for, мы помещаем это значение суммы в массив.
Когда цикл заканчивается, мы используем методы Math.max() и Math.min(), чтобы вычислить максимальные и минимальные значения в нашем массиве итогов и распечатать их.
console.log(Math.min(...totals) + " " + Math.max(...totals));
Вот остальная часть нашего кода:
function miniMaxSum(arr) {
let totals = [];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
for (let i = 0; i < arr.length; i++) {
let filtered = arr.filter(function(value, index, arr) {
return i !== index;
});
totals.push(filtered.reduce(reducer));
}
console.log(Math.min(...totals) + " " + Math.max(...totals));
}