简体   繁体   English

在 javascript 中使用 reduce 和 recursion 来展平嵌套数组

[英]Use reduce and recursion in javascript to flatten nested array

I have found this interesting code example which flattens an array using the recursion and reduce function instead of flat .我发现了这个有趣的代码示例,它使用recursion来展平数组并reduce function 而不是flat I get what it does except the following:我得到了它的作用,除了以下内容:

  1. acc = acc.concat(flatWithRec(item)); why accumulator is being reassign?为什么累加器被重新分配? how is it possible in reduce function?如何减少 function? and why use concat here?为什么在这里使用concat

  2. return acc; why acc is being returned?为什么 acc 被退回? is it a new Flat Array each time function is called?每次调用 function 时,它是一个新的平面阵列吗?

  3. is there a way to, still, use recursion and make it easier for the reader to understand?有没有办法仍然使用递归并使读者更容易理解?

Please clarify请说清楚

 function flatWithRec(arr) { const flatArray = arr.reduce((acc, item) => { if (Array.isArray(item)) { acc = acc.concat(flatWithRec(item)); } else { acc.push(item); } return acc; }, []); return flatArray; } console.log(flatWithRec([1, [2, 3, [4], [5, 6, [7]] ]])) // output: [1, 2, 3, 4, 5, 6, 7])

  1. The accumulator is an array.累加器是一个数组。 You reassign it to give it the new array containing the items of the one you have at the beginning of the loop and the items of the array items to add.你重新分配它,给它一个新数组,其中包含你在循环开始时拥有的项和要添加的数组项的项。 As said in the comments, acc.concat returns a new array containing the items of the arrays passed in parameter.正如评论中所说, acc.concat返回一个新数组,其中包含传入参数的 arrays 的项目。 See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat请参阅https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat

  2. You need to return the accumulator at the end of each loop for the new value to be taken in account at the next loop.您需要在每个循环结束时返回累加器,以便在下一个循环中考虑新值。

  3. Javascript recursive array flattening Javascript 递归数组展平

  1. acc = acc.concat(flatWithRec(item)); why accumulator is being reassign?为什么累加器被重新分配? how is it possible in reduce function?如何减少 function? and why use concat here?为什么在这里使用concat

The accumulator ( acc ) is a function argument, and can be re-assigned, although it's not a good practice to do so.累加器 ( acc ) 是一个 function 参数,可以重新分配,尽管这样做不是一个好习惯。 Concat combines two items (array or otherwise), and returns a new array, so you need to assign it to the acc as the result of the current loop. Concat 结合两个项目(数组或其他),并返回一个新数组,因此您需要将其分配给acc作为当前循环的结果。

  1. return acc; why acc is being returned?为什么 acc 被退回? is it a new Flat Array each time function is called?每次调用 function 时,它是一个新的平面阵列吗?

The accumulator holds the current state of the reduced items, in your case the current flat array after each loop.累加器保存减少项目的当前 state,在您的情况下,每个循环后的当前平面数组。 You need to return it, so the next loop can continue to accumulate.您需要将其返回,以便下一个循环可以继续累积。

  1. is there a way to, still, use recursion and make it easier for the reader to understand?有没有办法仍然使用递归并使读者更容易理解?

My take on flatWithRec - always concat, but if it's an array call flatWithRec on it before concatenating:我对flatWithRec的看法 - 总是连接,但如果它是一个数组,在连接之前调用flatWithRec

 function flatWithRec(arr) { return arr.reduce((acc, item) => acc.concat( Array.isArray(item)? flatWithRec(item): item ), []); } const result = flatWithRec([1, [2, 3, [4], [5, 6, [7]]]]) console.log(result) // output: [1, 2, 3, 4, 5, 6, 7])

So, the callback for the reduce method runs for every item in the array and whatever is returned from iteration x is passed as the first argument to iteration x+1 .因此, reduce方法的回调针对数组中的每个项目运行,并且从迭代 x返回的任何内容都作为第一个参数传递给迭代 x+1 So, it is essential to make sure that during every iteration the correct state is returned.因此,必须确保在每次迭代期间返回正确的 state。

acc = acc.concat(flatWithRec(item)) Why accumulator is being reassigned? acc = acc.concat(flatWithRec(item))为什么要重新分配累加器? How is it possible in reduce function?如何reduce function? And why use concat here?为什么在这里使用concat

So, we are assigning acc the return value of concat because concat does not change the original array, it returns a fresh array.因此,我们将concat的返回值分配给acc ,因为concat不会更改原始数组,它会返回一个新数组。 Accumulator is just like any other parameter so you can reassign.累加器就像任何其他参数一样,因此您可以重新分配。 Not at all necessary to use concat (see my solution at the end using push and spread ) .完全不需要使用concat (请参阅最后使用pushspread的解决方案)

return acc; Why acc is being returned?为什么acc被退回? Is it a new flat array each time the function is called?每次调用 function 时,它是一个新的平面阵列吗?

As, already mentioned you need to return the correct state from the callback.如前所述,您需要从回调中返回正确的 state。 And yes, during each iteration a new array is being created (which is not that performant, see my solution at the end)是的,在每次迭代期间,都会创建一个新数组(这不是那么高效,请参阅最后的解决方案)

Is there a way to still use recursion and make it easier for the reader to understand?有没有办法仍然使用递归并让读者更容易理解?

Easier for reader I can't tell, but here's my solution using => functions and spread .我不知道对读者来说更容易,但这是我使用=> functionsspread的解决方案。

 const flatWithRec = (arr) => arr.reduce((acc, item) => ( Array.isArray(item)? acc.push(...flatWithRec(item)): acc.push(item), acc ), []); console.log(flatWithRec([1, [2, 3, [4], [5, 6, [7]]]]));

Yes, there is a way to use recursion and make it easier to understand:是的,有一种方法可以使用递归并使其更易于理解:

 function f(A, i=0){ return i == A.length? []: (Array.isArray(A[i])? f(A[i]): [A[i]]).concat(f(A, i+1)); } var A = [1, [2, 3, [4], [5, 6, [7]]]]; console.log(JSON.stringify(A)); console.log(JSON.stringify(f(A)));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM