Выровнять вложенные массивы с помощью рекурсии (и без использования циклов) - PullRequest
0 голосов
/ 10 февраля 2019

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

var input = [['A','B'],1,2,3,['C','D']]
  1. Проверьте первый элемент, чтобы увидеть, является ли массив или не используется Array.isArray (input)
  2. Если первый элемент является массивом, вызовите функцию, первый элемент ['A, 'B'] в качестве аргумента.
  3. Первым элементом вложенного массива является 'A', который не является массивом, поэтому вставьте этот элемент в массив результатов и сдвиньте его.Повторите вызов функции.

При попытке выровнять вложенные массивы с помощью рекурсии моя входная переменная для функции продолжает переназначаться, не давая мне снова вызвать функцию с использованием исходного массива.Как предотвратить переназначение исходной входной переменной?

Я понимаю, что это не полное решение, однако я застреваю при перемещении первого элемента из вложенного массива.

Я прошел шаг за шагом с этой функцией,но должно быть что-то, чего мне не хватает, очень поможет другой набор глаз.

Я также использовал свой инструмент разработчика Chrome, устанавливая точки останова для пошагового мониторинга функции.

//Defining original input variable
var input = [['A','B'],1,2,3,['C','D']]

function flat(array){
    var result = []
    var firstElement = array[0]

//CHECK IF FIRST ELEMENT IS ARRAY OR NOT
    if(Array.isArray(firstElement)){
    return flat(firstElement)  
    } 


//IF ELEMENT NOT ARRAY, PUSH ELEMENT TO RESULT
    else{result.push(firstElement)
    array.shift() //removing child element
    return (flat(array)) //call function on same array
    }

if(array.length===0){return result}

}

Первая итерация: firstElement = ['A', 'B'], Array.isArray (firstElement) будет истинным, поэтому вызовите flat (firstElement)

Вторая итерация: firstElement= 'A', Array.isArray (firstElement) имеет значение false, поэтому мы 1. прыгаем вниз, чтобы вставить этот элемент в результат 2. удаляем 'A' с помощью array.shift () 3. Вызываем flat (array), где array isnow ['B']

Третья итерация: firstElement = 'B', Array.isArray (firstElement) = falseЯ сбросил результат, когда вспомнил функцию.2. удалить 'B' с помощью array.shift (), массив теперь пуст, -> [] 3. Как я могу выйти и использовать flat () в исходном входном массиве?

Ответы [ 2 ]

0 голосов
/ 10 февраля 2019

Ваш код не учитывает следующие элементы, если первый элемент является массивом.В приведенном ниже решении используется array.concat(...) для объединения результата рекурсии (спускаясь по дереву), а также для объединения результатов обработки остальной части списка (на том же уровне).Визуализация проблемы в виде дерева часто помогает с рекурсиями. ИМО:

 [] 1 2 3 []
 |         |
A []      C D
   |
  B C

Так что, возможно, здесь более ясно, что мы должны согласовать как результат рекурсии, так и результат "шага" кправо (снова рекурсия), которое в противном случае было бы циклом, повторяющим массив.

var input = [['A',['B', 'C']],1,2,3,['C','D']]

function flat(array) {
    var result = []
    if (array.length == 0) return result;
  
    if (Array.isArray(array[0])) {
        result = result.concat(flat(array[0]));    // Step down
    } else {
        result.push(array[0]);
    }
    result = result.concat(flat(array.slice(1)))   // Step right

    return result;
}

console.log(flat(input));
// ["A", "B", "C", 1, 2, 3, "C", "D"]

Это несколько аналогично версии с циклами:

function flat(array) {
    var result = []

    for (var i = 0; i < array.length; i++) {
        if (Array.isArray(array[i])) {
            result = result.concat(flat(array[i]));
        } else {
            result.push(array[i]);
        }
    }
    return result;
}

РЕДАКТИРОВАТЬ: В целях отладки вы можете отслеживать глубину, чтобы помочь получить обзорчто происходит где:

var input = [['A',['B', 'C']],1,2,3,['C','D']]
function flat(array, depth) {
    var result = []
    if (array.length == 0) return result;

    if (Array.isArray(array[0])) {
        result = result.concat(flat(array[0], depth + 1));
    } else {
        result.push(array[0]);
    }
    var res1 = flat(array.slice(1), depth);
    console.log("Depth: " + depth + " | Concatenating: [" + result + "]  with: [" + res1 + "]");
    result = result.concat(res1)

    return result;
}

console.log(flat(input, 0));
0 голосов
/ 10 февраля 2019

Если вы хотите избежать циклов, и я рассматриваю concat вставку / расширение массивов как циклов, вам нужно передать массив результатов в вашу функцию.

const input = [['A', 'B'], 1, 2, 3, ['C', 'D']]

// Start the function with an empty result array.
function flat(array, result = []) {
  if (!array.length)
    return result

  // Extract first element.
  const first = array.shift()

  // Call the function with the array element and result array.
  if (Array.isArray(first))
    flat(first, result)
  // Or add the non array element.
  else
    result.push(first)

  // Call the function with the rest of the array and result array.
  flat(array, result)
  return result

}

console.log(flat(input))
...