Как не терять результат при рекурсии?

Задача: написать функцию, которая рекурсивно будет убирать вложенные подмассивы. (Аналог 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 шт):

Автор решения: Alexandr

Передавайте 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'

→ Ссылка
Автор решения: BERTOLDO

Просто передайте результирующий массив вторым аргументом.

+ Доработан алгоритм. Тот что в условии - неправильный.

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));

→ Ссылка
Автор решения: Nikolya Shirshov

Пример реализации без мутирования аргументов:

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));

→ Ссылка
Автор решения: xmikex

Можете просто обернуть рекурсивную функцию во внешней функции, которую вызываете:

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;
    }
→ Ссылка
Автор решения: Grundy

Чтобы убрать первый уровень вложенности, можно воспользоваться методом .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));

→ Ссылка