由于被@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;
}
的第二个挑战是但使代码在时间和存储器的效率更高。这可以通过将列表结构的数量限制为1来完成。您可以通过使用一个称为累加器的概念来完成此操作:通过递归过程更新的变量。首先,我们需要初始化变量:
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
的末尾;否则我们执行递归调用。
此功能所做的最后一件事情是在初始steamer
调用target
将填充嵌套列表中的所有元素后返回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因此每次调用'steamrollArray'都会共享并修改它。 –