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

  • Массив.прототип.фильтр
  • Array.prototype.map
  • Array.prototype.sort
  • Array.prototype.reduce

Массив.прототип.фильтр

Фильтр перебирает каждый элемент массива. Если условие выполнено (и возвращено true), элемент возвращается в исходный массив. Довольно просто. Если возвращается false (или ничего не возвращается), элемент выбрасывается.

Это означает, что если в массиве 10 элементов, а фильтр соответствует только 6, будут возвращены только 6 элементов (в отличие от Array.prototype.map).

Пример

Используйте Array.prototype.filter для фильтрации людей с именами, длина которых превышает 4 символа.

Создайте массив людей с именами разной длины.

const people = ['John','Tom','Bartholomew'];

Отфильтруйте людей с именами, длина которых превышает 4 символа.

people.filter(function(person) {
    if (person.length > 4) {
        return true;
    }  
})
// returns ['Bartholomew']

Или используя синтаксис стрелки.

people.filter(person => person.length > 4);
// returns ['Bartholomew']

Резюме

Фильтр позволяет быстро и легко удалить из массива элементы, не соответствующие определенным критериям.

Array.prototype.map

Map также перебирает каждый элемент массива, но возвращает новый массив той же длины.

В отличие от filter, который возвращает исходный элемент (если возвращено значение true), map позволяет возвращать новый элемент с любым значением (обычно на основе оригинальный товар).

Также в отличие от filter, если ничего не возвращается, элемент не выбрасывается, он возвращается как неопределенный.

Это означает, что если массив содержит 10 элементов, а map возвращает только 6 элементов, будут возвращены все 10 элементов, 4 из которых не определены.

Пример

Используйте Array.prototype.map, чтобы добавить «Симпсон» в качестве фамилии для людей, совпадающих только с именами, длина которых превышает 4 символа.

const people = ['John','Tom','Bartholomew'];

Сопоставьте массив людей.

people.map(function(person) {
    if (person.length > 4) {
        return person + ' Simpson';
    }  
})
// returns [undefined, undefined, 'Bartholomew Simpson']

Map дважды возвращает значение undefined, так как «John» и «Tom» содержат более 4 символов, и при повторении этих двух элементов значения не возвращаются.

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

// Using arrow syntax to help readability
people
    .filter(person => person.length > 4) // removes 'John' and 'Tom'
    .map(person => person + ' Simpson');
// returns ['Bartholomew Simpson']

Резюме

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

Array.prototype.sort

Сортировка упорядочивает массив элементов по возрастанию или по убыванию.

Пример 1

Используйте Array.prototype.sort для сортировки массива имен.

const names = ['John', 'Tom', 'Bartholomew'];

Сортировать по имени.

names.sort();
// returns ["Bartholomew", "John", "Tom"]

Сортировка автоматически сортирует строки в алфавитном порядке. Чтобы получить результаты в обратном порядке, добавьте метод Array.prototype.reverse.

names.sort().reverse();
// returns ["Tom", "John", "Bartholomew"]

Пример 2

Сортировка массива возрастов.

const age = [13, 10, 7];

Сортировать по возрасту.

people.sort();
// returns [10, 13, 7]

Это неожиданно. Числа не отсортированы от меньшего к большему.

Это связано с тем, что внутренняя сортировка преобразует каждое значение в строку. 10, 13, 7 становятся «10», «13» и «7».

В порядке Unicode «10» и «13» стоят перед «7».

Ну, это просто здорово.

К счастью, sort использует необязательную функцию сравнения. Это великолепно, потому что позволяет сортировке по-настоящему сиять.

Пример 3

Отсортируйте массив возрастов, на этот раз правильно с помощью функции сравнения.

const age = [13, 10, 7];

Сортировать по возрасту.

age.sort(function(a, b) {
    return a - b;
})
// returns [7, 10, 13]

Это правильный результат. Путем сравнения каждого значения со следующим значения сортируются, а затем возвращаются по порядку.

За кулисами сортировка перебирает два значения массива за раз. В первый раз a 13, а b 10.

  • Если a - b меньше нуля, a сортируется по более низкому индексу.
  • Если a - b больше 0, a сортируется по более высокому индексу.
  • Если a - b равно 0, то a и b остаются без изменений.

Это может показаться сложным, но это простой способ сортировки массивов строк, чисел и даже объектов с вложенными свойствами.

В следующем примере используется сортировка массива объектов с использованием функции сравнения для сортировки по возрасту.

Пример 4

Отсортируйте массив объектов по возрасту.

const people = [
    {name: 'John', age: 13},
    {name: 'Tom', age: 10},
    {name: 'Bartholomew', age:7}
];

Сортировать по возрасту.

people.sort(function(a, b){
    return a.age - b.age;
});
// returns [
    {name: 'Bartholomew', age:7},
    {name: 'Tom', age: 10},
    {name: 'John', age: 13}
   ]

Последний пример сортировки каждого человека по имени.

people.sort((a, b) => {
    const aName = a.name.toUpperCase();
    const bName = b.name.toUpperCase();
    if (aName < bName) {
      return -1;
    }
    if (aName > bName) {
      return 1;
    }
    // names must be equal
    return 0;
});
// returns [
    {name: 'Bartholomew', age:7},
    {name: 'John', age: 13}
    {name: 'Tom', age: 10}
   ]

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

Резюме

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

Перерыв на выпивку

По желанию, сейчас самое время наполнить чашку любимым напитком.

Array.prototype.reduce

Reduce перебирает массив и принимает 2 аргумента. Первый — это обратный вызов, который принимает 4 аргумента. Второе — это начальное значение.

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

Накопитель — это просто промежуточный итог, который передается от каждой итерации к следующей. Это просто возвращаемое значение (что бы ни возвращалось) внутри редукторного обратного вызова.

Наконец, начальное значение является вторым аргументом метода reducer. Это необязательный параметр, который можно использовать в качестве отправной точки для конечного значения.

Пример 1

Понимание аккумулятора.

const numbers = [10, 30, 60];
numbers.reduce(function(accumulator, currentValue, currentIndex, array) {
    console.log(accumulator);
    return accumulator + currentValue;
},0)
// console.log shows 0 <- the initial value
// console.log shows 10 <- the initial value + currentValue, 10
// console.log shows 40 <- 10 + currentValue which is now 30
// console.log shows 100 <- 40 + currentValue which is now 60
// returns 100

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

Чтобы облегчить чтение следующих примеров, имена аргументов в обратном вызове сокращены.

numbers.reduce(function(acc, val, i, array) {
    // code here..
})

Пример 2

Добавьте значения в массив.

const people = [13, 10, 7];
people.reduce(function(acc, val, i, array) {
    return acc + val;
},0)
// returns 30

Пример 3

Теперь, чтобы получить немного сложнее. Получите среднее число из всех значений в массиве.

const people = [13, 10, 7];
people.reduce(function(acc, val, i, array) {
    if (i === array.length - 1) {
      const numOfPeople = i + 1;
      return ((acc + val) / numOfPeople)
    }
    return acc + val;
},0)
// returns 10

Мы должны проверить — это последняя итерация? Если это так, мы возвращаем среднее значение конечного результата на основе длины массива.

Помните, что i равно 0 на первой итерации. К последней итерации i равно 2. Но array.length равно 3. Так что это причина синтаксиса.

Пример 4

Аналогичен предыдущему примеру, но с массивом объектов.

Получите средний возраст людей в массиве людей.

const people = [
    {name: 'John', age: 13},
    {name: 'Tom', age: 10},
    {name: 'Bartholomew', age:7}
];
people.reduce(function(acc, val, i, array) {
    if (i === array.length - 1) {
      const numOfPeople = i + 1;
      return ((acc + val.age) / numOfPeople)
    }
    return acc + val.age;
},0)
// returns 10

Пример 5

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

const teams = ['teamA', 'teamA', 'teamB', 'teamC', 'teamC', 'teamC', 'teamD'];
teams.reduce(function(acc, val, i, array) {
    if (!acc[val]) {
      acc[val] = 0;
    }
    acc[val]++;
    return acc;
},{})
// returns {
      teamA: 2,
      teamB: 1,
      teamC: 3,
      teamD: 1
   }

В этом последнем примере проверяется, есть ли у аккумулятора свойство с текущим значением. Если нет, он создает его, а затем увеличивает значение на 1. Конечным результатом является объект команд со значениями, основанными на том, сколько раз они появлялись в массиве.

Резюме

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

Вывод

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

От простого фильтра и сопоставления до более сложных методов сортировки и сокращения — эти методы могут очищать код и делать вещи проще рассуждать.

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