Кратко
СкопированоМетод flat позволяет сформировать массив, применяя функцию к каждому элементу, затем уменьшает вложенность, делая этот массив плоским, и возвращает его.
Был добавлен в стандарте ES2019. Если вы поддерживаете браузеры, выпущенные раньше 2018 года, то вам понадобится полифил.
Пример
СкопированоПолучить плоский список из сложной структуры
СкопированоПредставим, что у нас есть список заказов пользователей из которого мы хотим понять, какие товары заказывают:
const orders = [ { id: 1, products: [ { name: 'Чизкейк', price: 1.99 }, { name: 'Бисквит', price: 4.99 }, ] }, { id: 2, products: [ { name: 'Шоколад', price: 5.59 }, { name: 'Зефир', price: 8.99 }, ] }]
const orders = [
{
id: 1,
products: [
{ name: 'Чизкейк', price: 1.99 },
{ name: 'Бисквит', price: 4.99 },
]
},
{
id: 2,
products: [
{ name: 'Шоколад', price: 5.59 },
{ name: 'Зефир', price: 8.99 },
]
}
]
Одним из решений будет сначала дважды вызвать метод map, а затем сделать массив плоским с помощью метода flat
Сначала воспользуемся методом map:
orders.map( (order) => order.products.map(product => product.name))
orders.map(
(order) => order.products.map(product => product.name)
)
Получим следующий результат:
[['Чизкейк', 'Бисквит'], ['Шоколад', 'Зефир']]
[['Чизкейк', 'Бисквит'], ['Шоколад', 'Зефир']]
Обратите внимание на вложенность массивов, нам нужно от неё избавиться. Для этого применим метод flat:
orders .map((order) => order.products.map((product) => product.name)) .flat()
orders
.map((order) => order.products.map((product) => product.name))
.flat()
['Чизкейк', 'Бисквит', 'Шоколад', 'Зефир']
['Чизкейк', 'Бисквит', 'Шоколад', 'Зефир']
Другое решение этой задачи — сразу вызвать метод flat (ведь статья у нас именно про него):
orders.flatMap( (order) => order.products.map(product => product.name))
orders.flatMap(
(order) => order.products.map(product => product.name)
)
Увидим что функция применилась, вложенность уменьшилась и мы получили только названия продуктов из массива products:
['Чизкейк', 'Бисквит', 'Шоколад', 'Зефир']
['Чизкейк', 'Бисквит', 'Шоколад', 'Зефир']
Модификация структуры данных
СкопированоПредставим, что мы пишем корзину для интернет-магазина. Товары в корзине храним в виде объекта:
const cart = [ { name: 'Телефон', count: 1, price: 500, }, { name: 'Ноутбук', count: 1, price: 800, }]
const cart = [
{
name: 'Телефон',
count: 1,
price: 500,
},
{
name: 'Ноутбук',
count: 1,
price: 800,
}
]
Если человек покупает телефон, то требуется добавить зарядное устройство. Для этого вызовем flat и будем возвращать массив из телефона и зарядного устройства вместо одного объекта с телефоном.
cart.flatMap( (item) => { if (item.name === 'Телефон') { return [item, { name: 'Зарядное устройство', count: item.count, price: 50, }] } return item })
cart.flatMap(
(item) => {
if (item.name === 'Телефон') {
return [item, {
name: 'Зарядное устройство',
count: item.count,
price: 50,
}]
}
return item
}
)
flat сделает массив плоским и мы получим массив элементов в корзине:
[ { name:'Телефон', count:1, price:500, }, { name:'Зарядное устройство', count:1, price:50, }, { name:'Ноутбук', count:1, price:800, },]
[
{
name:'Телефон',
count:1,
price:500,
}, {
name:'Зарядное устройство',
count:1,
price:50,
}, {
name:'Ноутбук',
count:1,
price:800,
},
]
Эту же задачу можно решить и другим способом, применив метод reduce. Но это отразится на читаемости кода, а этим пренебрегать не стоит!
cart.reduce((list, item) => { if (item.name === 'Телефон') { list.push(item, { name: 'Зарядное устройство', count: item.count, price: 50, }) } else { list.push(item) } return list}, [])
cart.reduce((list, item) => {
if (item.name === 'Телефон') {
list.push(item, {
name: 'Зарядное устройство',
count: item.count,
price: 50,
})
} else {
list.push(item)
}
return list
}, [])
Как пишется
СкопированоКак и другим похожим методам, flat необходимо передать колбэк-функцию, которая будет возвращать какое-то значение. Именно это значение попадёт в итоговый массив.
Функция, которую мы передаём в flat, принимает три аргумента:
current— текущий элемент массива.Value index— индекс текущего элемента в массиве.array— массив, который мы перебираем.
Возвращает 0 или более элементов массива.
Как понять
СкопированоМетод идентичен последовательному вызову map с параметром depth , соответственно, применяется для трансформации исходных данных, с уменьшением вложенности.
Данный метод более эффективный, чем вызов этих функций по отдельности, поскольку обход массива совершается только один раз.
Разница между map() и flatMap()
СкопированоРассмотрим на примере разницу между методами map и flat. Возьмём массив с данными о местоположении и представим, что нужно получить (или преобразовать) координаты:
const allActivities = [ { title: 'Офис', coordinates: [50.123, 3.291] }, { title: 'Спортзал', coordinates: [1.238, 4.292] },]const mappedCoordinates = allActivities.map(activity => activity.coordinates)const flatMappedCoordinates = allActivities.flatMap(activity => activity.coordinates)
const allActivities = [
{ title: 'Офис', coordinates: [50.123, 3.291] },
{ title: 'Спортзал', coordinates: [1.238, 4.292] },
]
const mappedCoordinates = allActivities.map(activity => activity.coordinates)
const flatMappedCoordinates = allActivities.flatMap(activity => activity.coordinates)
Теперь взглянем на результаты с применением map:
[[50.123, 3.291], [1.238, 4.292]]
[[50.123, 3.291], [1.238, 4.292]]
И на результат с flat:
[50.123, 3.291, 1.238, 4.292]
[50.123, 3.291, 1.238, 4.292]
Вместо того чтобы использовать метод map и получить массивы координат, а затем сократить массив, вы можете сразу использовать flat.
Разница между flat() и flatMap()
СкопированоМетод flat делает входной массив плоским, глубина указывается в аргументах.
Метод flat применяет функцию, трансформируя массив и делает массив плоским. Два в одном.