Как я могу рекурсивно преобразовать вложенный массив в плоский массив?

#javascript #arrays #recursion #nested

#javascript #массивы #рекурсия #вложенный

Вопрос:

Я пытаюсь преобразовать этот вложенный массив в плоский массив. При использовании этого способа решения кажется, что каждый раз, когда я вызываю arrayFlattener (элемент), newArr становится пустым массивом. Кто-нибудь может мне помочь с этим? Спасибо.

 const arrayFlattener = (arr) => {
    let newArr = [];
    
    for (let i = 0; i < arr.length; i  ) {
        let element = arr[i];
        if (Array.isArray(element)){
            newArr.push(arrayFlattener(element));
            
        } else {
            newArr.push(element);
        }
    }
    return newArr;
}
console.log(arrayFlattener(['I', 'am', 'working', ['on', 'another', 'level']]));  

Комментарии:

1. Было бы полезно, если бы вы отметили этот вопрос языком, на котором работаете. (Я бы сделал это за вас, но я не узнаю синтаксис.)

2. Является ли производительность требованием для использования рекурсии?

3. Вы ищете общую рекурсию, хвостовую рекурсию или итеративную рекурсию?

Ответ №1:

flat выполните работу с depth param уровнем, указывающим, насколько глубоко структура вложенного массива должна быть сглажена.

Пример

 const arr = ['I', 'am', 'working', ['on', 'another', 'level'], 'now', ["now", ["hello", "you you"]]]

console.log(arr.flat(2))  

Ответ №2:

Ваш код и теория в порядке. Вы просто выбрали неправильный метод. Используйте concat вместо push (чтобы расширить результат, а не вставлять в него):

 const arrayFlattener = (arr) => {
    let newArr = [];
    
    for (let i = 0; i < arr.length; i  ) {
        let element = arr[i];
        if (Array.isArray(element)){
            newArr = newArr.concat(arrayFlattener(element));
            
        } else {
            newArr.push(element);
        }
    }
    return newArr;
}
console.log(arrayFlattener(['I', 'am', 'working', ['on', 'another', 'level']]));  

Ответ №3:

Вы можете использовать flatMap

 let newArr = ['I', 'am', 'working', ['on', 'another', 'level']].flatMap(el=>el);

console.log(newArr);  

или используйте flat

 var arr1 = [1, 2, [3, 4]];
arr1.flat(); 
// [1, 2, 3, 4]

var arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]

var arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2); // depth argument to flatten the array
// [1, 2, 3, 4, 5, 6]
  

Комментарии:

1. Я согласен, если вам нужно реализовать рекурсию, вы можете сделать так, как ответил @Andreas, но также я считаю, что реализация браузера будет быстрее, чем реализация рекурсии.

Ответ №4:

В настоящее время ваша функция не выравнивает массив, а просто выполняет синтаксический анализ по каждому отдельному элементу массива. Он по-прежнему возвращает ту же структуру массива.

Чтобы сгладить массив, вы также должны передать результирующий массив, чтобы отдельный элемент можно было поместить прямо в результирующий массив вместо создания другого массива и отправки его в результирующий массив (который создает ту же исходную структуру массива)

 let newArr = [];
const arrayFlattener = (arr, result) => {
    for (let i = 0; i < arr.length; i  ) {
        let element = arr[i];
        if (Array.isArray(element)){
            result = arrayFlattener(element, result);
            
        } else {
            result.push(element);
        }
    }
    return result
}
console.log(arrayFlattener(['I', 'am', 'working', ['on', 'another', 'level'], 'now'], newArr));  

Комментарии:

1. Почему бы не использовать flattenMap?

2. Это кажется немного странным. Я думаю, что более распространено вводить просто входные данные и ожидать результата, а не вводить одновременно входные данные и указатель на результат, если только последнее не является абсолютно необходимым.

Ответ №5:

Вот три решения

Вы можете использовать .flatMap и рекурсию или

 const flatten = (xs) =>
  Array.isArray(xs) ? xs.flatMap(flatten) : [xs]

const array = ['I', 'am', 'working', ['on', 'another', ['level']]]

console.log(flatten(array))  

вы можете использовать .reduce и рекурсию

 const flatten = (xs) =>
  xs.reduce(
    (y, x) => y.concat(Array.isArray(x) ? flatten(x) : [x]),
    [])

const array = ['I', 'am', 'working', ['on', 'another', ['level']]]

console.log(flatten(array))  

или еще лучше просто использовать .flat

 const flatten = (xs) =>
  xs.flat(Infinity)

const array = ['I', 'am', 'working', ['on', 'another', ['level']]]

console.log(flatten(array))