Я вижу пару проблем:
Array#concat
- это не на месте функция. Он возвращает новый массив, который должен быть назначен или возвращен acc = acc.concat(flatten(val));
или return acc.concat(flatten(val));
. val
s не добавляются в аккумулятор ни в одной точке. return val;
нарушает обычный контракт функции обратного вызова, которая должна возвращать аккумулятор для следующего элемента, который будет использоваться.
const flatten = a =>
a.reduce((acc, val) =>
acc.concat(Array.isArray(val) ? flatten(val) : val)
, [])
;
console.log(flatten([1,2,3,4,[5,6,[7,[8,9]]]]));
Кроме того, я думаю, reduce
здесь не самая подходящая функция. Всякий раз, когда я обнаруживаю, что сокращаю массив и не фильтрую какие-либо элементы, я знаю, что могу рефакторинг в Array#map
, который является более конкретным reduce
. Предпочитайте reduce
только тогда, когда filter
или map
трудно использовать, например, при создании объектов.
const flatten = a =>
[].concat(...a.map(val => Array.isArray(val) ? flatten(val) : val))
;
console.log(flatten([1,2,3,4,[5,6,[7,[8,9]]]]));
Это позволяет избежать всего довольно неловкого бизнеса с аккумуляторами.
Но если у вас нет доступа к оператору распространения и вы ищете полную совместимость,тогда reduce
снова полезен, потому что он позволяет нам вызывать concat
для каждого элемента:
function flatten(a) {
return a.reduce(function (acc, val) {
return acc.concat(Array.isArray(val) ? flatten(val) : val);
}, []);
}
console.log(flatten([1,2,3,4,[5,6,[7,[8,9]]]]));