Паттерны работы с массивами
Паттерны работы с массивами
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.