Реализуйте общие редукторы sum, min и max

Агрегатная функция в запросе SQL выполняет вычисление одного или нескольких значений и возвращает одно значение.

  • COUNT подсчитывает количество строк.
  • SUM складывает все значения из данного столбца.
  • MIN и MAX возвращают наименьшее и наибольшее значения из указанного столбца.
  • AVG вычисляет среднее число из всех значений в данном столбце.

Во всех примерах мы будем использовать следующую таблицу.

Articles
Title                              | Views
3 Ways of Invoking a Method        | 123
3 Iterables Converted Into Arrays  | 88
How to Find Elements in Array      | 402
How to Position a Div              | 103

Ниже представлен соответствующий массив объектов статьи.

const articles = [
  {title: '3 Ways of Invoking a Method', views: 123},
  {title: '3 Iterables Converted Into Arrays', views: 88},
  {title: 'How to Find Elements in Large Arrays', views: 402},
  {title: 'How to Position a Div Element', views: 103} 
]

Метод reduce объединяет все значения из массива в одно значение с помощью функции редуктора. Он выполняет заданную функцию редуктора для каждого элемента массива.

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

Считать

Следующий запрос SQL подсчитывает количество строк в Articles таблице.

SELECT COUNT(*)
FROM Articles
--4

Чтобы получить количество объектов в массиве, мы можем просто получить доступ к свойству length.

articles.length

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

function count(total, article){
 return (article != null && article !== undefined) ? total + 1 : total;
}

Общее совокупное значение инициализируется 0. Обратите внимание на второй аргумент, переданный методу reduce.

const noOfArticles= articles.reduce(count, 0);
//4

Сумма

Следующий запрос SQL извлекает общее количество просмотров всех статей в таблице.

SELECT SUM(Views)
FROM Articles
--716

Мы можем вычислить общий вид из массива объектов, используя следующую функцию редуктора. Требуется общее количество просмотров, вычисленное на данный момент, и текущая статья. Он извлекает количество просмотров из статьи и добавляет его к общему количеству.

function sum(total, article){
  const {views} = article;
  return total + views;
}

При выполнении этого вычисления мы начинаем с 0 в качестве начальной суммы просмотров.

const total = articles.reduce(sum, 0);
//716

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

function sum(propName){}

Дело в том, что метод reduce вызывает функцию редуктора с двумя аргументами. Первый - это агрегированное значение, вычисленное на данный момент, а второй аргумент - это текущий элемент. Метод reduce не отправляет имя свойства, которое мы хотим принять.

Решение состоит в том, чтобы заставить функцию sum принимать имя необходимого свойства, а затем возвращать функцию-редуктор, требуемую методом reduce.

Вот пример.

function sum(propName){
  return function(total, obj){
    const {[propName]: value} = obj;
    return total + value;
  }
}

Обратите внимание, как мы динамически извлекаем свойство из объекта в новую переменную с именем value, используя синтаксис деструктурирующего присваивания.

const {[propName]: value} = obj;

Ниже функция sum создает функцию редуктора, используемую методом reduce.

const total = articles.reduce(sum('views'), 0);
//716

Функция, принимающая на вход другую функцию или возвращающая функцию, является функцией более высокого порядка. sum - функция высшего порядка.

Мин.

В следующем запросе SQL используется агрегатная функция MIN, чтобы показать минимальное количество просмотров в статье.

SELECT MIN(Views)
FROM Articles
//88

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

function min(propName){
  return function(minimum, obj){
    const {[propName]: value} = obj;
    return value < minimum ? value : minimum;
  }
}

Нам нужно ответить на еще один вопрос. При вычислении сумма 0 была начальным значением. Какое начальное значение при вычислении минимума?

Хороший вариант - использовать количество просмотров из первой статьи в качестве начального минимального значения.

const minum = articles.reduce(min('views'), articles[0].views);
//88

Максимум

В приведенном ниже запросе SQL применяется агрегатная функция MAX, чтобы найти максимальное количество просмотров.

SELECT MAX(Views)
FROM Articles

Функция MAX принимает имя свойства для проверки и возвращает функцию-редуктор. Редуктор получает вычисленное максимальное значение на данный момент и текущий объект. Когда текущий объект имеет количество просмотров больше, чем вычисленное значение, тогда текущее количество просмотров становится новым максимумом. В противном случае возвращается уже вычисленное максимальное значение.

function max(propName){
  return function(maximum, obj){
    const {[propName]: value} = obj;
    return value > maximum ? value : maximum;
  }
}

При вызове метода reduce мы можем начать с 0 как начального максимального количества просмотров.

const total = articles.reduce(max('views'), 0);
console.log(total);
//402

Средн.

В приведенном ниже запросе вычисляется среднее количество просмотров всех статей с помощью функции AVG.

SELECT AVG(Views)
FROM Articles
--179

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

const total= articles.reduce(sum('views'), 0);
const averageViews =  total / articles.length;
//179

Последние мысли

Агрегатная функция в SQL-запросе позволяет агрегировать значения из нескольких строк в вычисленное значение.

Метод уменьшения массива позволяет агрегировать все элементы массива в одно значение.

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

Спасибо за чтение.

Вы также можете проверить Как найти элементы в больших массивах.