Как не терять результат при рекурсии?
Задача: написать функцию, которая рекурсивно будет убирать вложенные подмассивы. (Аналог Array.prototype.flat)
Я написал следующий код:
const result = [];
function flat(array) {
for (let i = 0; i < array.length; i++) {
if (Array.isArray(array[i])) {
return flat(array[i]);
} else {
result.push(array[i]);
}
}
return result;
}
const array = [1, 2, 3, [4, 5, 6, [7, 8, 9], 10]];
console.log(flat(array));
Он работает, но мне нужно поместить const result = [] в саму функцию. Соответственно, если я его помещаю в нее с данной реализацией, рекурсия его каждый раз обновляет.
Какой наиболее элегантный выход из этого положения?
Ответы (5 шт):
Передавайте result просто как параметр:
function flat(array, result=[]) {
for (let i = 0; i < array.length; i++) {
if (Array.isArray(array[i])) {
flat(array[i] , result);
} else {
result.push(array[i]);
}
}
return result;
}
const array = [1, 2, 3, [4, 5, 6, [7, 8, 9], 10],11];
console.log(flat(array));
да, передав параметром все стало как надо, но пока не понимаю как избавиться от вышеупомянутой проблемы
а проблема была в том, что после return совершается выход из всех функций сразу, просто надо убрать 'return'
Просто передайте результирующий массив вторым аргументом.
+ Доработан алгоритм. Тот что в условии - неправильный.
function flat(array, res = []) {
for (let i = 0; i < array.length; i++) {
if (Array.isArray(array[i])) {
flat(array[i], res);
}
else {
res.push(array[i])
};
}
return res;
}
const array = [1, 2, 3, [4, 5, 6], 7, 10, [1, 2, 3, [0],
[10, 99, [90], 2]
]];
console.log(flat(array));
Пример реализации без мутирования аргументов:
function flat(array) {
let result = [];
for (let i = 0; i < array.length; i++) {
if (Array.isArray(array[i])) {
result = result.concat(flat(array[i])); // Объединяем массив с подмассивами
} else {
result.push(array[i]);
}
}
return result;
}
const array = [1, [2, 3, [4, 5, 6, [7, 8, 9]]], 10];
console.log(flat(array));
Можете просто обернуть рекурсивную функцию во внешней функции, которую вызываете:
function flat(array)
{
const result = [];
function inner(array) {
for (let i = 0; i < array.length; i++) {
if (Array.isArray(array[i])) {
inner(array[i]);
} else {
result.push(array[i]);
}
}
}
inner(array);
return result;
}
Чтобы убрать первый уровень вложенности, можно воспользоваться методом .concat, например
[].concat(...array);
Чтобы применить ко всем уровням, нужно применить функцию для каждого элемента из array и результат передать в concat.
для этого можно воспользоваться методом .map
[].concat(...array.map(flat));
Осталось добавить ограничение рекурсии: в случае когда передали не массив - нужно вернуть сам элемент
if (!Array.isArray(array)) return array;
В итоге можно получить следующее:
function flat(array) {
if (!Array.isArray(array)) return array;
return [].concat(...array.map(flat))
}
const array = [1, 2, 3, [4, 5, 6, [7, 8, 9], 10], 11];
console.log(flat(array));