Используйте .map(), .reduce() и .filter()
В наши дни функциональное программирование произвело настоящий фурор в мире разработки.
В этой статье подробно рассматриваются сопоставление, фильтр и уменьшение. Понимание этих трех функций является важным шагом на пути к написанию чистого функционального кода и открывает двери для чрезвычайно мощных методов функционального и реактивного программирования.
Любопытно? Давайте углубимся.
.карта()
Поясню, как это работает, на простом примере. Допустим, вы получили массив, содержащий несколько объектов, каждый из которых представляет человека. В конце концов, вам действительно нужен массив, содержащий только идентификатор каждого фильма.
// What we have at the moment var movies = [ { id: 75, name: 'JAWS' }, { id: 94, name: 'Pulp Fiction' }, { id: 84, name: 'Star Wars: The Phantom Menace' }, { id: 77, name: 'Star Wars A New Hope' } ]; // What we need [75, 94, 84, 77]
Есть много способов добиться этого. Возможно, вы захотите сделать это, создав пустой массив, а затем используя .forEach()
, .for(...of)
или простой .for()
для достижения своей цели, верно?
Давайте сравним .forEach()
с .map()
.
var moviesIds = []; movies.forEach(function (movie) { moviesIds.push(movie.id); });
Обратите внимание, что вам нужно заранее создать пустой массив, если мы используем .forEach()
? Давайте посмотрим, как мы можем сделать это с помощью .map()
.
var moviesIds = movies.map(function (movie) { return movie.id });
Мы можем быть еще более краткими со стрелочными функциями.
const moviesIds = movies.map(movie => movie.id);
.уменьшать()
Как и .map()
, .reduce()
также запускает обратный вызов для каждого элемента массива. Отличие заключается в том, что reduce передает результат этого обратного вызова (накопитель) из одного элемента массива в другой.
Аккумулятор может быть практически любым (целое число, строка, объект и т. д.) и должен быть создан или передан при вызове .reduce()
.
Допустим, у нас снова есть массив с этими фильмами и их соответствующими годами:
var movies = [ { id: 10, name: "JAWS", years: 1975, }, { id: 2, name: "Pulp Fiction", years: 1994, }, { id: 41, name: "Star Wars: The Phantom Menace", years: 1999, }, { id: 99, name: "Star Wars A New Hope", years: 1977, } ];
Нам нужно знать общее количество лет всех из них. С .reduce()
все довольно просто:
var totalYears = movies.reduce(function (accumulator, movie) { return accumulator + movie.years; }, 0);
После запуска обратного вызова для каждого элемента массива, сокращение вернет окончательное значение нашего аккумулятора (в нашем случае: 7945
).
Давайте посмотрим, как это можно сократить с помощью стрелочных функций ES6:
const totalYears = movies.reduce((acc, movie) => acc + movie.years, 0);
Теперь предположим, что я хочу найти, какой фильм является самым старым. Для этого я также могу использовать сокращение:
var mostOldMov = movies.reduce(function (oldest, movie) { return (oldest.years || 0) > movie.years ? oldest : movie; }, {});
Как видите, использование .reduce()
— это простой способ сгенерировать одно значение или объект из массива.
.фильтр()
Что, если у вас есть массив, но вам нужны только некоторые его элементы?
Вот наши данные:
var movies = [ { id: 10, name: "JAWS", type: Adventure, }, { id: 2, name: "Pulp Fiction", type: Crime, }, { id: 41, name: "Star Wars: The Phantom Menace", type: SiFi, }, { id: 99, name: "Star Wars A New Hope", type: SiFi, } ];
Скажем, сейчас нам нужны два массива: один для SiFi, другой для остальных. С .filter()
проще не бывает!
var siFiMovies = movies.filter(function (movie) { return movie.type === "SiFi"; }); var otherMovies = movies.filter(function (movie) { return movie.type !== "SiFi"; });
Вот и все! А со стрелочными функциями еще короче:
const siFiMovies = movies.filter(movie => movie.type === "SiFi"); const otherMovies = movies.filter(movie => movie.type !== "SiFi");