flatMap
невероятно полезен для коллекций, но javascript не предоставляет один, имея Array.prototype.map
. Почему?
Есть ли способ эмулировать flatMap
в javascript как простым, так и эффективным способом без определения flatMap
вручную?
flatMap
невероятно полезен для коллекций, но javascript не предоставляет один, имея Array.prototype.map
. Почему?
Есть ли способ эмулировать flatMap
в javascript как простым, так и эффективным способом без определения flatMap
вручную?
Обновление: Array.prototype.flatMap
находится на пути к собственному ECMAScript. Это в настоящее время на этапе 4.
Он широко поддерживается во многих средах. Посмотрите, работает ли он в вашем браузере, используя этот фрагмент ниже -
const data =
[ 1, 2, 3, 4 ]
console.log(data.flatMap(x => Array(x).fill(x)))
// [ 1, 2, 2, 3, 3, 3, 4, 4, 4, 4 ]
flatMap
был одобрен TC39 как часть ES2019 (ES10). Вы можете использовать это так:
[1, 3].flatMap(x => [x, x + 1]) // > [1, 2, 3, 4]
Вот моя собственная реализация метода:
const flatMap = (f, arr) => arr.reduce((x, y) => [...x, ...f(y)], [])
Я знаю, что вы сказали, что не хотите сами определять его, но эта реализация является довольно тривиальным определением.
Кроме того, это с той же страницы github:
Вот немного более короткий способ использования es6 spread, аналогичный renaudtertrais - но используя es6 и не добавляя к прототипу.
var flatMap = (a, cb) => [].concat(...a.map(cb))
const s = (v) => v.split(',')
const arr = ['cat,dog', 'fish,bird']
flatMap(arr, s)
Может ли это помочь?
Следует отметить (благодаря @ftor), что это последнее "решение" страдает от "Максимального размера стека вызовов", если вызывается в очень большом массиве (например, 300 тыс. элементов) a
.
Lodash предоставляет функцию плоской карты, которая для меня практически эквивалентна Javascript, предоставляющей ее изначально. Если вы не являетесь пользователем Lodash, то метод ES6 Array.reduce()
может дать вам тот же результат, но вы должны отобразить, а затем сгладить дискретными шагами.
Ниже приведен пример каждого метода, который отображает список целых чисел и возвращает только шансы.
Lodash:
_.flatMap([1,2,3,4,5], i => i%2 !== 0 ? [i] : [])
ES6 уменьшить:
[1,2,3,4,5].map(i => i%2 !== 0 ? [i] : []).reduce( (a,b) => a.concat(b), [] )
Я сделал что-то вроде этого:
Array.prototype.flatMap = function(selector){
return this.reduce((prev, next) =>
(/*first*/ selector(prev) || /*all after first*/ prev).concat(selector(next)))
}
[[1,2,3],[4,5,6],[7,8,9]].flatMap(i => i); //[1, 2, 3, 4, 5, 6, 7, 8, 9]
[{subarr:[1,2,3]},{subarr:[4,5,6]},{subarr:[7,8,9]}].flatMap(i => i.subarr); //[1, 2, 3, 4, 5, 6, 7, 8, 9]
Один довольно краткий подход - использовать Array#concat.apply
:
const flatMap = (arr, f) => [].concat.apply([], arr.map(f))
console.log(flatMap([1, 2, 3], el => [el, el * el]));
Теперь у нас есть flatMap()
в Javascript! И это поддерживается довольно хорошо
Метод flatMap() сначала отображает каждый элемент с помощью функции отображения, а затем выравнивает результат в новый массив. Он идентичен карте(), за которой следует квартира() глубины 1
const dublicate = x => [x, x];
console.log([1, 2, 3].flatMap(dublicate))