Используйте .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");