2016-04-23 4 views
0

Я делаю каток костер в freeCodeCamp я не могу понять, почему мой код не работает и он идет только для первого элемента в массивеСвести вложенный массив

function steamrollArray(arr) { 
    // I'm a steamroller, baby 


    var flat = []; 

    for(i=0; i < arr.length; i++){ 
     if(Array.isArray(arr[i])){ 
      flat = flat.concat(steamrollArray(arr[i])); 
     } else { 
      flat.push(arr[i]); 
     } 
    } // end of the for loop 


    return flat; 
} 
+0

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

+0

да он может! Почему? –

+6

'var i = 0'. [Без 'var',' i' является глобальной переменной] (http://stackoverflow.com/questions/1470488/what-is-the-function-of-the-var-keyword-and-when-to-use -it-or-omit-it), поэтому каждый вызов 'steamrollArray' делит его и изменяет. –

ответ

0

выглядит как Ионафан был прав, я делал я совместно всеми вложенными массивами так просто изменить I к Var I

0

Как комментирует @Jonathan проблема заключается в том, что вы используете счетчик i который не объявлен в функции и, таким образом, глобальный. В результате рекурсивных вызовов изменит i вызывающего абонента и т.д.

 
function steamrollArray(arr) { 
    // I'm a steamroller, baby 
    var flat = []; 

    for(var i=0; i < arr.length; i++){ 
     if(Array.isArray(arr[i])){ 
      flat = flat.concat(steamrollArray(arr[i])); 
     } else { 
      flat.push(arr[i]); 
     } 
    } // end of the for loop 
    return flat; 
} 

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

 
function steamrollArray(arr) { 
    return steamer(arr,[]); 
} 

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

 
function steamer (arr,target) { 
    if(Array.isArray(arr)) { 
    var n = arr.length; 
    for(var i = 0; i < n; i++) { 
     steamer(arr[i],target); 
    } 
    } else { 
    target.push(arr); 
    } 
    return target; 
} 

Что один делает проходящий через цель рекурсивного перебора дерева массива. В случае, если значение оказывается скаляром (Array.isArray возвращает false), мы добавляем элемент в конец target; в противном случае мы выполняем рекурсивный вызов.

Последнее, что эта функция делает, возвращает target, после начального вызова steamertarget будет заполнен всеми элементами во вложенном списке.

Преимуществом является то, что мы не нужны дорогие concat функции, но только использовать push функцию O (N) раз. Если мы делаем абстракцию времени обработки, необходимого для построения массива (предположим, что push работает в O (1) раз), алгоритм теперь работает в O (n) время и память с n количество листов в списке дерево.

0

попробуйте перезаписать массив следующим способом, используйте res [], чтобы сохранить результат;

function steamrollArray(arr) { 
    var res=[]; 
    function recurse(array) 
    { 
    for(var i = 0; i < array.length; i++) 
    { 
     if(!Array.isArray(array[i])) 
     res.push(array[i]); 
     else 
     recurse(array[i]); 
    } 
    } 
    recurse(arr); 
    return res; 
} 
0

Побочные эффекты, ES6, вы можете достичь глубокого расплющить итеративным рисунка с использованием .splice

function flatten(arr) { 
    let i = 0; 
    while (i < arr.length) { 
     if (Array.isArray(arr[i])) arr.splice(i, 1, ...arr[i]); 
     else ++i; 
    } 
    return arr; 
} 

напримерИспользование

flatten([1, [2], [[3]], [4, [5, [6]]], [[[7], 8], 9]]); 
// [1, 2, 3, 4, 5, 6, 7, 8, 9] 

Если вы не хотите, побочные эффекты, .slice перед тем,

functon flatClone(arr) { 
    return flatten(arr.splice()); 
} 
0
function steamrollArray(arr) { 
    return String(arr).split(',').map(Number); } 

Если он работает во всех ваших случаях, это работает на примере «сплющить» выше , дайте мне знать, если я что-то пропустил.

Смежные вопросы