我正在通过免费JavaScript课程,我偶然发现了这个“压路机”挑战。来自python的我非常喜欢一行解决方案,所以我成功地为这个挑战编写了一个:
function steamrollArray(arr) {
return Array.isArray(arr) ? [].concat(...arr.map(steamrollArray)) : arr;
}
steamrollArray([1, [2], [3, [[4]]]]) // returns [1, 2, 3, 4]其目标基本上是使任意深度的数组变平。但让我感到困惑的是,为什么看似相似的代码表现得非常不同(对JavaScript来说仍是新生事物)。我在一开始写的东西不起作用,但我通过试用获得的代码(主要是错误)起作用了:
[...arr.map(steamrollArray)] // this doesn't work, returns an unchanged array
[].concat(...arr.map(steamrollArray)) // this works, returns a flat array这对我来说很奇怪,因为递归的“展开”意味着它应该是相反的。
[...arr.map(steamrollArray)]
[1, ...[2], ...[3, ...[...[4]]]] // this should work
[].concat(...arr.map(steamrollArray))
[].concat(...[1, [].concat(...[2]), [].concat(...[3, [].concat(...[].concat(...[4]))])]) // what 'is going on'有人能解释一下这种行为吗?
发布于 2022-10-21 19:55:57
来自MDN的报价
然后,对于每个参数,它的值将连接到数组中-对于普通对象或原语,参数本身将成为最终数组的一个元素;用于数组.,参数的每个元素将独立地添加到最终数组中。
您可以在下面观察到这种行为;尽管第二个调用使用了一个数组,但两者都为我们提供了[1, 2, 3, 4, 5, 6]。
console.log([1, 2, 3].concat(4, 5, 6));
console.log([1, 2, 3].concat([4, 5, 6]));
如果要连接整个数组,则必须将其包装在另一个数组中:
console.log([1, 2, 3].concat([[4, 5, 6]])); // [1, 2, 3, [4, 5, 6]]那么这与你的问题有什么关系呢?好吧..。如果我们有一个类似于[1, 2, [3, 4], 5, [6]]的数组,并将其扩展到concat中,我们将得到如下所示:
console.log([].concat(1, 2, [3, 4], 5, [6]));
..。本质上是“平缓”它的一个层次。您的函数是递归的,因此它像这样平放数组,直到它完全平坦。
发布于 2022-10-21 19:59:05
Array.prototype.concat的参数(如果它们是数组的话)本质上被平放到生成的数组中。
[2].concat(3, [4, 5])[2, 3, 4, 5]检查结果。类似的
[].concat(3, [4, 5])[3, 4, 5]检查结果。
但是,将数组扩展到另一个数组并不会对扩展数组的每个元素执行这样的平坦处理。
const arr = [3, [4, 5]];
const newArr = [...arr];获取arr的每个元素,并将其放入一个新的数组中--但就这样,给出[3, [4, 5]] --原始数组的相同值,但在不同的数组中。
关于您问题中的代码:
[...arr.map(steamrollArray)]失败,因为是steamrollArray完成了扁平化操作--但是您还需要将每个返回的数组都压平。例如,如果您传入[[1, 2], [3, [4, 5]]]
[...[[1, 2], [3, [4, 5]]].map(steamrollArray)]
[...[[1, 2], [3, 4, 5]]]这不会使顶层变平。但是[].concat(...arr.map(steamrollArray))可以工作,因为concat (肤浅地)将每个数组参数都平放到结果中。
发布于 2022-10-21 20:08:18
所以其他人回答了你的问题,但是这里有一些简化的代码
const steamrollArray1 = arr => Array.isArray(arr) ? [].concat(...arr.map(steamrollArray1)) : arr;
const steamrollArray2 = arr => Array.isArray(arr) ? arr.flat(Infinity) : arr;
console.log(
steamrollArray1([1, [2], [3, [[4]]]])
); // returns [1, 2, 3, 4]
console.log(
steamrollArray2([1, [2], [3, [[4]]]])
); // returns [1, 2, 3, 4]
https://stackoverflow.com/questions/74158560
复制相似问题