Некоторые считают, что изучение того, как использовать следующие встроенные методы прототипа массива, является стартовым лекарством для функционального программирования.
- Массив.прототип.фильтр
- 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 берет массив и использует накопитель и каждое значение, чтобы свести данные к одному значению. Уменьшенное значение может быть числом или строкой. это также может быть динамически сгенерированный объект со свойствами и значениями. Это лишь некоторые из возможностей использования сокращения.
Вывод
Я не мастер этих методов. Я хотел написать это исключительно для того, чтобы заставить себя присмотреться и узнать о них больше. Я многому научился, пока писал.
От простого фильтра и сопоставления до более сложных методов сортировки и сокращения — эти методы могут очищать код и делать вещи проще рассуждать.
Я уверен, что есть более эффективные способы использования этих техник помимо уровней в моих примерах. Но если вы вынесли что-то положительное из прочтения этого поста, я надеюсь, что он пригодится вам в вашей собственной работе.