Javascript-用于展平数组的递归/for循环
因此,这里有一个解决阵列平坦问题的示例解决方案。我的问题不是“如何”展平阵列。相反,我试图理解在这个递归中发生的一些底层功能 此解决方案将遍历原始数组的每个元素,通过将这些元素放回函数分解为数组的所有元素,直到它们不再是数组并可以推送到新数组 我的问题是,“for”循环如何跟踪元素通过函数返回的所有时间,以及如何继续循环它当时正在处理的“原始”数组的其余部分?它必须以某种方式保持跟踪,否则每次元素是数组并被放回时,当前循环都会被缩短。希望我的问题有意义Javascript-用于展平数组的递归/for循环,javascript,arrays,recursion,Javascript,Arrays,Recursion,因此,这里有一个解决阵列平坦问题的示例解决方案。我的问题不是“如何”展平阵列。相反,我试图理解在这个递归中发生的一些底层功能 此解决方案将遍历原始数组的每个元素,通过将这些元素放回函数分解为数组的所有元素,直到它们不再是数组并可以推送到新数组 我的问题是,“for”循环如何跟踪元素通过函数返回的所有时间,以及如何继续循环它当时正在处理的“原始”数组的其余部分?它必须以某种方式保持跟踪,否则每次元素是数组并被放回时,当前循环都会被缩短。希望我的问题有意义 function steamrollArr
function steamrollArray(array) {
var flatArray = [];
flatten(array);
function flatten(array) {
for (var i = 0; i < array.length; i++) {
if (Array.isArray(array[i])) {
flatten(array[i]);
} else {
flatArray.push(array[i]);
}
}
}
return flatArray;
}
steamrollArray([1, [2], [3, [[4]]]]);
函数数组(数组){
var flatArray=[];
展平(阵列);
函数展平(数组){
对于(var i=0;i
它实际上并不会通过只发生一次的函数“返回”元素。它检查元素是否为数组,然后在该数组中循环
如果不是数组,则将其推送到flatArray
。这里的递归是,如果任何元素是数组,那么它将通过展平函数。然后,若该数组中有一个元素,那个么该元素被发送到一个数组中,以此类推
让我们举一个例子:[1,2],[3,[[4]]]]
我们开始循环->
- 索引0是1而不是数组,因此它被推送到flatArray
- 索引1是一个数组,所以我们递归-在这里我们有一个2-然后被推
- 索引2是一个数组,所以我们递归,内部数组的索引0是一个非数组3,所以它被推送。然后我们有最后一个索引-一个数组,我们递归到其中,找到另一个数组-再次递归-最后得到4,我们推
var item = [1, [2, 3], 4]
展平(项目)
的执行将是:
Loop 1:
Push 1
Loop 2:
Start a call to flatten with [2, 3]
Loop 1:
push 2
Loop 2:
push 3
End loop
Loop 3:
Push 4
End Loop.
关键是,它只是执行一个步骤的过程。它不必“记住”它在哪里,当函数返回时,javascript只是从调用函数的地方继续处理
你可能希望复习一下 结果数组
flatary
位于helper函数的词法闭包中,因此非数组的元素被推到这个位置,它们在结果中的放置顺序与它们的迭代顺序相同
当其中一个元素是数组时,它调用flatte(array[i])
,在返回之前将该元素的元素展平。与所有函数一样,语句的执行需要在下一个语句完成之前完成,调用函数根本不会取消当前函数。它将继续运行,直到结束或返回语句
想象一下这个功能:
function test () {
console.log("hello, ");
console.log("world!");
}
调用该语句时,它会等待整个console.log(“hello,”)
完成,然后再执行语句二(console.log(“world!”)
)。若它是递归调用,那个么该调用需要在执行语句2之前完成。它适用于所有函数调用,不只是递归调用 每个递归步骤的“跟踪”与任何其他方法调用的工作方式相同;javascript引擎跟踪变量和作用域,无论何时在中调用新方法
对于您的特定示例,当flant
函数不再嵌套时,可能更容易看到发生了什么
function steamrollArray(array) {
var flatArray = [];
flatten(array, flatArray);
return flatArray;
}
function flatten(array, flatArray) {
flatArray = flatArray || [];
for (var i = 0; i < array.length; i++) {
if (Array.isArray(array[i])) {
flatten(array[i]);
} else {
flatArray.push(array[i]);
}
}
}
steamrollArray([1, [2], [3, [[4]]]]); # [1, 2, 3, 4]
现在更明显的是递归发生的位置和方式。每当一个数组被“发现”时,它也会被展平。将值推送到新数组中,或推送到作为第二个参数传递的数组中。每次在for
循环中调用flatten
时,位于i
位置的数组本身被展平并推到flatArray
上。由于flatArray
也会递归地传递给flat
函数,因此所有值都将被收集到该数组中。我有一个更简单的解决方案,可用于数组中的任何嵌套级别
function flattenArray(arr){
for(var i=0;i<arr.length;i++){
if(arr[i] instanceof Array){
Array.prototype.splice.apply(arr,[i,1].concat(arr[i]))
i--;
}
}
return arr;
}
函数阵列(arr){
对于(var i=0;i使用
循环以及其他两种方法展平阵列的解决方案
使用进行循环的操作
let数组=[1,2],[3,4]];
让输出=[];
让数组=(arr)=>{
对于(让一个arr){
数组.isArray(a)?数组(a):输出.push(a);
}
返回输出;
}
console.log(数组(数组));
它遍历数组项,如果数组的当前项是数组,它将该数组项作为参数递归调用展平函数,直到它不是数组而是整数。然后它将其推送到称为flatarray的外部数组,返回并继续上一个数组的下一项。会问很多问题在本主题中,首先:“它必须以某种方式跟踪”-当您从f1()
中调用函数f2()
时,然后在f2()
完成f1()后
在它停止的地方继续。因此,如果你从循环中调用函数,那么当函数完成时,循环将继续。在你的例子中,函数递归地调用自己
function flattenArray(arr){
for(var i=0;i<arr.length;i++){
if(arr[i] instanceof Array){
Array.prototype.splice.apply(arr,[i,1].concat(arr[i]))
i--;
}
}
return arr;
}