Learning Book

Паттерны работы с массивами

Паттерны работы с массивами

Chaining — цепочки методов

Методы, возвращающие массив, можно цепочкой:

const users = [
  { name: 'Иван', age: 25, role: 'admin', active: true },
  { name: 'Мария', age: 30, role: 'user', active: false },
  { name: 'Пётр', age: 22, role: 'user', active: true },
  { name: 'Анна', age: 35, role: 'admin', active: true },
];

// Найти имена активных юзеров старше 24, отсортировать по имени
const result = users
  .filter(u => u.active)          // убрать неактивных
  .filter(u => u.age > 24)        // убрать молодых
  .sort((a, b) => a.name.localeCompare(b.name, 'ru')) // сортировка
  .map(u => u.name);              // извлечь имена

// result = ['Анна', 'Иван']
Каждый метод в цепочке получает результат предыдущего. Цепочка читается сверху вниз — это декларативное описание трансформации.

Иммутабельность

Важно не мутировать массив — вместо этого создавать новый:

const todos = [
  { id: 1, text: 'Задача 1', done: false },
  { id: 2, text: 'Задача 2', done: false },
];

// Добавить задачу (иммутабельно)
const withNew = [...todos, { id: 3, text: 'Задача 3', done: false }];

// Отметить задачу выполненной (иммутабельно)
const updated = todos.map(todo =>
  todo.id === 1 ? { ...todo, done: true } : todo
);

// Удалить задачу (иммутабельно)
const withoutFirst = todos.filter(todo => todo.id !== 1);

Object.groupBy — группировка (ES2024)

const fruits = [
  { name: 'яблоко', type: 'круглый' },
  { name: 'апельсин', type: 'круглый' },
  { name: 'банан', type: 'длинный' },
];

const grouped = Object.groupBy(fruits, fruit => fruit.type);
// {
//   'круглый': [{name: 'яблоко', ...}, {name: 'апельсин', ...}],
//   'длинный': [{name: 'банан', ...}]
// }

Группировка через reduce (если groupBy недоступен)

const groupBy = (arr, key) =>
  arr.reduce((groups, item) => {
    const group = item[key];
    groups[group] = groups[group] ?? [];
    groups[group].push(item);
    return groups;
  }, {});

Уникальные значения

// Через Set
const unique = [...new Set([1, 2, 2, 3, 3, 4])]
// [1, 2, 3, 4]

// Уникальные объекты по полю
const uniqueUsers = users.filter(
  (user, idx, arr) => arr.findIndex(u => u.id === user.id) === idx
);

Каждый метод в цепочке проходит весь массив. filter().map() — два прохода. reduce() — один:

// Два прохода (но читаемо)
const result = arr.filter(x => x > 0).map(x => x * 2);

// Один проход (менее читаемо, быстрее)
const result = arr.reduce((acc, x) => {
  if (x > 0) acc.push(x * 2);
  return acc;
}, []);

Для маленьких массивов (< 100 000 элементов) — используйте цепочки. Для больших — measure first, optimize second.