Плаский масив з багатовимірного
«Розплющити» масив означає перетворити вкладену структуру на один плаский список значень. У сучасному JavaScript для цього є метод flat(), який приймає глибину розгортання; решта способів (рекурсія, flatMap(), toString()) залишаються корисними в окремих випадках.
Теорія
TL;DR
arr.flat()розгортає один рівень вкладеності.arr.flat(2)розгортає два рівні,arr.flat(Infinity)розгортає все.- Жоден із цих способів не змінює вихідний масив, усі повертають новий.
- До ES2019 писали рекурсивний
flattenнаreduce()плюсArray.isArray(). flatMap()цеmap()плюс розгортання одного рівня за один прохід.toString().split(',')працює лише для чисел і рядків і повертає рядки.
Швидкий приклад
Маємо масив:
const arr = [1, [2, 3], [4, [5, 6]]];Хочемо отримати [1, 2, 3, 4, 5, 6]:
console.log(arr.flat(Infinity)); // [1, 2, 3, 4, 5, 6]flat() і глибина розгортання
Найпростіший спосіб це flat() (ES2019 і новіші):
const flattened = arr.flat();
console.log(flattened); // [1, 2, 3, 4, [5, 6]]За замовчуванням flat() розгортає лише один рівень вкладеності. Глибину можна задати аргументом:
const deeplyFlattened = arr.flat(2);
console.log(deeplyFlattened); // [1, 2, 3, 4, 5, 6]flat(1)це один рівень,flat(2)це два рівні,flat(Infinity)це повне розгортання, незалежно від глибини.
Приклад із глибокою вкладеністю:
const nested = [1, [2, [3, [4]]]];
console.log(nested.flat(Infinity)); // [1, 2, 3, 4]Це найзручніший і найсучасніший спосіб зробити масив пласким. Бонусом flat() прибирає порожні комірки розрідженого масиву: [1, , 3].flat() дає [1, 3].
Рекурсія, спосіб до flat()
function flatten(arr) {
return arr.reduce(
(acc, val) => acc.concat(Array.isArray(val) ? flatten(val) : val),
[]
);
}
console.log(flatten([1, [2, [3, 4]], 5]));
// [1, 2, 3, 4, 5]- перевіряємо кожен елемент: якщо це масив, викликаємо
flattenрекурсивно; - якщо ні, додаємо значення до результату.
Цей варіант досі корисний, коли потрібна власна логіка, наприклад пропускати null або розгортати лише певні гілки.
toString() для чисел і рядків
[1, [2, [3, 4]]].toString().split(',');
// ["1", "2", "3", "4"]Працює, тільки якщо в масиві немає об'єктів чи null, бо все перетворюється на рядки. Числа після такого перетворення теж стають рядками, тож це радше трюк, ніж робочий підхід.
flatMap() для перетворення разом із розгортанням
const arr = [1, 2, [3, 4]];
const result = arr.flatMap(x => (Array.isArray(x) ? x : [x]));
console.log(result); // [1, 2, 3, 4]flatMap() одночасно перетворює елементи і розгортає один рівень, тому він економить зайвий прохід порівняно з map().flat().
Порівняння способів
| Спосіб | Працює з | Глибина | Мутує | Сучасність |
|---|---|---|---|---|
arr.flat() | масив | 1 за замовчуванням | Ні | Так, ES2019 і новіші |
arr.flat(Infinity) | багатовимірний | усі рівні | Ні | Так |
| Рекурсія | масив | будь-яка | Ні | Так, універсально |
flatMap() | масив | 1 рівень | Ні | Так |
toString().split() | числа, рядки | усі рівні | Ні | Обмежено |
Підсумок: щоб зробити масив пласким,
javascriptconst flat = arr.flat(Infinity);це коротко, безпечно і зрозуміло.
Типові помилки
- Очікувати, що
flat()розгорне все. Без аргументу він знімає рівно один рівень; для глибокої структури потрібенflat(Infinity). - Вважати, що
flat()змінює масив. Він повертає новий масив, тому результат треба присвоїти:arr = arr.flat(). toString().split(',')на об'єктах. Об'єкти перетворяться на[object Object], аnullіundefinedстануть порожніми рядками.- Втрата типів після
split(). Числа повертаються рядками, тож потрібне додаткове.map(Number). - Рекурсія без базового випадку по типу. Якщо не перевіряти
Array.isArray(val), рядок теж піде в рекурсію, бо його можна ітерувати. flatMap()замість глибокого розгортання. Він знімає тільки один рівень, тому для[[1, [2]]]результат залишиться вкладеним.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.