Подтвердить что ты не робот

Почему нет Array.prototype.flatMap в javascript?

flatMap невероятно полезен для коллекций, но javascript не предоставляет один, имея Array.prototype.map. Почему?

Есть ли способ эмулировать flatMap в javascript как простым, так и эффективным способом без определения flatMap вручную?

4b9b3361

Ответ 1

Обновление: 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 ]

Ответ 2

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)], [])

Статья MDN на flatMap

Ответ 3

Я знаю, что вы сказали, что не хотите сами определять его, но эта реализация является довольно тривиальным определением.

Кроме того, это с той же страницы 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.

Ответ 4

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), [] )

Ответ 5

Я сделал что-то вроде этого:

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]

Ответ 6

Один довольно краткий подход - использовать Array#concat.apply:

const flatMap = (arr, f) => [].concat.apply([], arr.map(f))

console.log(flatMap([1, 2, 3], el => [el, el * el]));

Ответ 7

Теперь у нас есть flatMap() в Javascript! И это поддерживается довольно хорошо

Метод flatMap() сначала отображает каждый элемент с помощью функции отображения, а затем выравнивает результат в новый массив. Он идентичен карте(), за которой следует квартира() глубины 1

const dublicate = x => [x, x];

console.log([1, 2, 3].flatMap(dublicate))