Как комментирует @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
, после начального вызова steamer
target
будет заполнен всеми элементами во вложенном списке.
Преимуществом является то, что мы не нужны дорогие concat
функции, но только использовать push
функцию O (N) раз. Если мы делаем абстракцию времени обработки, необходимого для построения массива (предположим, что push
работает в O (1) раз), алгоритм теперь работает в O (n) время и память с n количество листов в списке дерево.
Может ли массив быть произвольным глубоко вложенным? –
да он может! Почему? –
'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' делит его и изменяет. –