.flatMap() — JavaScript — Дока
Кратко
СкопированоМетод 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)
)
Увидим что функция применилась, вложенность уменьшилась и мы получили только названия продуктов из массива
:
['Чизкейк', 'Бисквит', 'Шоколад', 'Зефир']
['Чизкейк', 'Бисквит', 'Шоколад', 'Зефир']
Модификация структуры данных
СкопированоПредставим, что мы пишем корзину для интернет-магазина. Товары в корзине храним в виде объекта:
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()
СкопированоРассмотрим на примере разницу между методами
и 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
применяет функцию, трансформируя массив и делает массив плоским. Два в одном.
Как получить все неуникальные значения в массиве JavaScript?
Иногда бывает нужно получить все повторяющиеся значения из массива JavaScript.
В этой статье мы рассмотрим способы получения всех неуникальных значений в массиве JavaScript.
Array.prototype.filter
Один из таких способов связан с использованием метода filter
массива JavaScript для возвращения массива, соответствующего заданному условию.
Он принимает функцию обратного вызова, возвращающую условие, которое должно быть у каждого возвращаемого элемента.
Задействуя метод filter
вместе с вызовом метода indexOf
в функции обратного вызова, мы проверяем, является ли встреченный элемент первым.
Для этого в массиве, в котором вызывается filter
, вызываем indexOf
, получаемый из третьего параметра функции обратного вызова.
Затем проверяем, совпадает ли возвращаемый индекс с тем, которому соответствует итерируемый элемент.
Например, напишем следующее:
const duplicates = [1, 2, 2, 4, 3, 4].filter((e, index, arr) => arr.indexOf(e) !== index)
console.log(duplicates)
Затем вызываем filter
с функцией обратного вызова, которая принимает параметры e
, index
и arr
, где:
e
— это элемент, по которому выполняется итеративный обход;index
— это индекс элементаe
;arr
— это массив, в котором вызываетсяfilter
.
Мы вызываем indexOf
в arr
с аргументом e
, чтобы вернуть индекс первого встреченного элемента e
в массиве arr
.
Несовпадение возвращаемого индекса с index
свидетельствует о том, что это встреченное значение не первое.
Следовательно, duplicates
(повторяющиеся значения) — это [2, 4]
, так как они дублируются в массиве.
Подсчет элементов
Посчитаем элементы в массиве, создав собственный объект для задания значения счетчика:
const obj = [1, 2, 2, 4, 3, 4] .map((val) => { return { count: 1, val } }) .reduce((a, b) => { a[b.val] = (a[b.val] || 0) + b.count return a }, {})const duplicates = Object.entries(obj) .filter(([, val]) => { return val > 1 }) .map(([key]) => +key) console.log(duplicates)
Вызываем map
для сопоставления каждой записи объекту со счетчиком count
, имеющим значение 1, и со значением элемента массива val
.
Затем вызываем reduce
для создания объекта со счетчиком каждого элемента, где каждый элемент будет ключом.
Делаем это, присваивая счетчик из a[b.val]
с (a[b.val] || 0) + b.count
.
В b.count
имеется новый счетчик.
И возвращаем a
, где содержатся все произведенные подсчеты.
Второй аргумент — пустой объект, поэтому создаем объект в конце.
Затем для получения повторяющихся значений мы берем все ключи со значением больше 1.
Для этого вызываем Object.entries
в obj
.
После чего вызываем filter
с функцией обратного вызова для возвращения любых записей со значением val
больше 1.
val
— это значение свойства объекта.
Затем вызываем
для получения ключа key
из массивов, содержащих пары «ключ-значение».
Получаем тот же результат, что и в предыдущем примере для duplicates
(повторяющихся значений).
Заключение
Для получения из массива повторяющихся значений используются различные методы массивов и объектов. Мы рассмотрели лишь малую их часть.
Читайте также:
- Утверждения, применяемые при импортировании в JavaScript
- JavaScript - идеальный выбор при аналитической обработке данных
- Советы по отладке JavaScript
Читайте нас в Telegram, VK и Яндекс.Дзен
Перевод статьи John Au-Yeung: How to Get All Non-Unique Values in a JavaScript Array?
Читайте также
11 способов перебора массива в Javascript
Ах… Javascript, наш любимый язык, Его свобода может быть как благословением, так и проклятием.
В этом посте мы рассмотрим 11 различных способов (в произвольном порядке) перебора массива (не объекта) в Javascript.
Давайте определим наш массив
Хорошо, это довольно простой массив, давайте двигаться дальше.
1- Верный старый forEach
Array. prototype.forEach
Классический массив forEach принимает два аргумента:
1- Функция, содержащая три параметра: текущий элемент, индекс и исходный массив.
2- A эта замена
для передачи функции обратного вызова (игнорируется стрелочными функциями).
Это наиболее рекомендуемый способ итерации, совместимый с IE9
2- Цикл for-in
Такое использование цикла не рекомендуется и иногда используется только для отладки, но вы можете столкнуться с ним в дикой природе, используемой в производстве. Он перебирает любое пользовательское свойство, определенное для объекта, за исключением свойств javascript по умолчанию. Он также работает для циклического перебора массивов, но если вы определите что-либо в прототипе массива, то он также будет полностью повторен.
3 — Цикл for-of (ES6)
Это один из самых щедрых видов циклов, он встроен в саму спецификацию языка. Он очень похож на цикл for-in, но основное различие между ними заключается в том, что for-of используется исключительно для типов коллекций (карты, наборы, массивы, массивы типов, списки узлов и т. д.). Это позволит избежать свойств объекта и может использоваться с любым объектом, который также реализует символ [Symbol.iterator] (см. Расширенное использование).
Основное отличие от Array.prototype.forEach
заключается в том, что вы можете использовать ключевое слово break
для остановки цикла и ключевое слово continue
для пропуска текущей итерации.
4 — Стиль C для цикла
Это один из наиболее часто используемых массивов в вычислительной технике. Его синтаксис унаследован от языка C и состоит из трех частей:
- Инициализатор индекса
- Состояние работы
- Модификатор индекса, который запускается в конце каждого цикла
Вы также можете использовать ключевые слова break
и continue
для этого типа цикла.
5 — Цикл «Пока»
Цикл while самый быстрый (по какой-то причине), его синтаксис очень прост:
- Условие выполнения
Если вы хотите использовать его для перебора массива, вам также потребуется отслеживать переменную индекса, что делает его действительно похожим на цикл в стиле C, но с недостатком, заключающимся в том, что индекс остается за пределами области видимости. петли.
Вы также можете использовать ключевые слова break
и continue
для этого типа цикла.
6. Цикл Do-while
Цикл do-while очень похож на цикл while, но он оценивает условие выполнения в конце выполнения, в результате чего цикл всегда выполняется хотя бы один раз. Это заставляет вас обрабатывать сценарий пустого массива, поскольку доступ к пустому массиву приведет к ошибке. Его синтаксис тоже прост:
- Состояние работы
О, и вы также можете использовать ключевые слова break
и continue
для такого рода циклов.
7 — Метод Map
Array.prototype.map
В ES5 добавлено три основных метода для итерации массива для создания нового массива. Одним из таких методов является карта
.
Функция карты принимает два аргумента:
1- Функция, которая содержит три параметра: текущий элемент, индекс и исходный массив.
2- A эта замена
для передачи функции обратного вызова (игнорируется стрелочными функциями).
Не следует изменять исходный массив.
8 — Метод фильтра
Array.prototype.filter
Функция фильтра используется для оценки логического выражения, если возвращается true, то итерируемый элемент остается в новом цикле, если возвращается false, то элемент будет проигнорирован и не будет присутствовать на новый массив.
Как и функция карты, функция фильтра принимает два аргумента:
1- Функция, которая содержит три параметра: текущий элемент, индекс и исходный массив.
2- A эта замена
для передачи функции обратного вызова (игнорируется стрелочными функциями).
Не следует изменять исходный массив.
9 — Метод уменьшения
Array.prototype.reduce
Функция reduce
отслеживает новый продукт и текущий элемент, а также получает параметр для начального значения нового продукта. Это может быть трудно понять в начале, но чем больше вы смотрите на примеры сокращения, тем легче вам становится понять синтаксис.
Метод сокращения получает следующие входные данные:
1- Функция, которая имеет продукт в качестве первого параметра, а текущий элемент повторяется в качестве второго параметра, третий параметр, который является текущим индексом элемента, и последний параметр, который обеспечивает доступ к исходному массиву.
2- Начальное значение, которое будет использоваться для продукта.
Метод сокращения обычно используется для синтеза всего массива в одно значение, например, для вычисления суммы.
10 — Метод соединения строки и массива
Array.prototype.join
Метод соединения имеет кое-что общее с последним введенным нами методом (reduce): он генерирует один вывод из массива, точнее, строки, и может работать только с массивами на основе строк.
Он имеет единственный ввод: строка-разделитель, которую нужно использовать.
11 — ES2018 для ожидания
Это одна из новейших функций, представленных в javascript, она позволяет нам размещать ожидание в наших циклах for of, позволяя им перебирать промисы и асинхронные значения (см. Функции асинхронного генератора).
Вы можете использовать для ожидания
вместе с функциями асинхронного генератора, чтобы указать циклы, которые будут ждать завершения текущего итерируемого промиса, или вы можете использовать его для ожидания массива промисов (вероятно, вам следует использовать Promise .все
для этого хотя).
Другой пример:
ES2019
Flat
метод Array.prototype.flat
Он перебирает основной массив для поиска вложенных массивов и выводит значения, содержащиеся в любом вложенном массиве, на верхний уровень.
Вы можете указать, насколько глубоко вы хотите углубиться в структуру массива, чтобы вывести значения массива на верхний уровень.
ES2019
Flatmap
метод Array.prototype.flatMap
Это точно так же, как карта
, за которой следует квартира
. Вы можете использовать это, чтобы сгладить произведение карты, которая создает вложенные массивы.
(Спасибо Пабло Обандо за эти предложения) 😄
Рекурсия
Вы можете использовать рекурсию для перебора массива, спасибо !
Рекурсия в функциональном смысле — это когда функция может вызывать сама себя, проходя через код. У этого есть некоторые преимущества:
1- Вы можете настроить свою петлю так, как хотите.
2- Функциональный подход.
3- Действительно полезно, когда вы имеете дело с другими типами структур, такими как деревья или круговые списки.
Но будьте осторожны , javascript имеет максимальный размер стека вызовов, это означает, что на каждой итерации вызов регистрируется в стеке вызовов, и если вызовов слишком много, то вы переполняете стек вызовов, вызывая исключение, рекурсивные вызовы также медленнее из-за этого поведения.
Вы даже можете создать смесь цикла C Style и цикла forEach!
Давайте продолжим и определим рекурсивную функцию для воспроизведения функциональности Array.prototype.forEach
:
Итак, вероятно, есть много способов перебрать массив в javascript, например, обратный do-while петли. или любой из других не очень популярных методов Array.prototype
, таких как every
, some
, reduceRight
или flatMap
, но вот некоторые из самых популярных способов перебора массива в JavaScript 🚀
Различные способы перебора массива в JavaScript
Несколько способов перебора массива в JavaScript: цикл for, цикл while, цикл for, map(), forEach(), filter() и reduce().
Опубликовано в·
Чтение: 5 мин.·
12 августа 2022 г.другие . Надеюсь, у вас есть четкое представление о массивах. Но прежде чем перейти к основному разделу, позвольте мне напомнить основы массива.
Что такое массив?
Массив — это сложная структура данных, используемая для последовательного хранения элементов одного и того же типа данных. Массивы являются статическими, и размер массива следует указывать при инициализации массива в коде. Но массив JavaScript отличается от традиционных массивов, где массивы являются динамическими — это означает, что нет необходимости указывать размер массива при инициализации, и любое количество элементов может быть помещено в массивы. Массивы JavaScript могут хранить значения любого типа данных — это означает, что элементы внутри массива могут быть любого размера, т. е. нет ограничений, что элементы должны быть одного типа.
Почему мы перебираем массив?
Так как массив хранит элементы в последовательном порядке, нам нужно пройти или перебрать массив, чтобы найти в нем нужный элемент. Обычно обход занимает время сложности O(n). Мы также пройдемся по массиву, чтобы изменить элементы массива или получить доступ к каждому элементу массива.
Различные методы обхода массива
Существует несколько методов обхода массива. Их:
- цикл for
- цикл while
- цикл for-of
- map()
- forEach()
- filter()
- reduce()
Это один из основных методы перебора массива. Цикл for можно использовать для обхода массива, используя длину массива. В цикле for следует упомянуть три условия.
- Начальное базовое условие
- Конечное условие
- Условие повторения (обычно увеличение или уменьшение)
Пример:
2. Цикл while
Цикл while работает аналогично циклу for, но принимает условие и будет выполняться до тех пор, пока данное условие не станет истинным. Если условие становится ложным, цикл while прерывается, и управление переходит к следующему оператору вне цикла. Операторы continue и break можно использовать внутри цикла while.
Пример:
3. Цикл for-of
Цикл for-of похож на цикл for-in в Python, где мы используем «in» в качестве ключевого слова, тогда как в JS «in» заменено на « из». Он используется для перебора массива и может напрямую обращаться к элементам без индексации, поскольку он дает элементы, а не индексирует, как фактический «цикл for».
Пример:
Это можно использовать, когда нам нужно просто получить доступ к элементам и не нужно манипулировать ими, поскольку мы не можем получить доступ к индексу элементов.
4. map()
Map() — это метод массива, который используется для последовательного применения функции или желаемого действия к каждому элементу массива, и результирующий массив будет возвращен как результат. Он вызывает функцию обратного вызова, а функция обратного вызова имеет три параметра: значение, индекс и массив. Элемент, возвращаемый функцией обратного вызова, будет сохранен в массиве с тем же индексом. Похоже на то, что вы берете элементы из одного массива, манипулируете ими и сохраняете их в новом массиве.
Пример: для работы с массивом
5. forEach()
forEach() также является методом массива и очень похож на функцию map(), тогда как единственное отличие состоит в том, что метод forEach() не вернуть что-либо. Это вернет undefined. Функции, которые могут быть реализованы с помощью метода map(), также могут быть реализованы с помощью forEach(), но для изменения элемента в новом массиве вручную требуются дополнительные усилия.
Пример:
6. filter()
Метод filter() аналогичен методу map(), но возвращаемый тип обратного вызова — логическое значение. Метод filter() возвращает массив. Он используется для фильтрации массива только с элементами, которые удовлетворяют заданному условию обратного вызова. Элементы, не удовлетворяющие заданному условию, не добавляются в возвращаемый массив. Если ни один из элементов не удовлетворяет условию, определенному в обратном вызове, возвращаемое значение будет пустым массивом, а не нулевым.
Пример: фильтрация нечетных чисел в массиве
7. reduce()
Простой способ объяснить функцию reduce() — объяснить ее на простом примере. Рассмотрим алгоритм добавления элементов в массив. Обычно мы определяем переменную с именем как сумму до 0, добавляем все элементы в переменную суммы и возвращаем ее.