使用reduce函数返回一个数组

77

为什么我想在reduce函数中使用push方法返回一个新数组时会出现错误,但是使用concat方法却可以毫无问题地返回一个新数组。

我只是想将一个数组传递给reduce函数并返回相同的数组。

var store = [0,1,2,3,4];

var stored = store.reduce(function(pV,cV,cI){
  console.log("pv: ", pV);
  return pV.push(cV);
},[]);

这会返回一个错误。但是当我使用concat函数时:

var store = [0,1,2,3,4];

var stored = store.reduce(function(pV,cV,cI){
  console.log("pv: ", pV);
  return pV.concat(cV);
},[]);

它返回相同的数组。

有什么想法吗?


6
return PV.push 的意思是,在下一次迭代中,PV 将是一个数字,而不是一个数组,因为 push 方法返回数组的长度。如果你想的话,可以使用 return pV.push(cV), pV;,但除了省略一行代码 pV.push(cV); return pV; 以外没有任何好处。 - Jaromanda X
1
如果你只想“复制”数组... var stored = store.slice(); 就可以了。 - Jaromanda X
1
@Andy 能否详细解释一下?文档 确切地 表明 map 方法对数组中的每个元素执行一次提供的回调函数,按顺序构造一个新数组,并将结果存储到新数组中,这似乎完美地描述了问题提问者所做的事情。 - Jamiec
1
@Andy - 你可以用鞋跟把钉子敲进墙里 - 但通常我们更喜欢选用正确的工具来完成任务。阅读这两种方法的文档,或者只需查看我的下面的答案。 - Jamiec
1
@Andy - 要往墙上钉钉子,你需要的是锤子,而不是鞋子(同样的道理适用)。 - Jamiec
显示剩余8条评论
6个回答

138

push 返回数组的新长度。

你需要的是最初提供的数组。

因此将代码更改如下。

var store = [0, 1, 2, 3, 4];

var stored = store.reduce(function(pV, cV, cI){
  console.log("pv: ", pV);
  pV.push(cV);
  return pV; // *********  Important ******
}, []);

concat 返回一个新数组,其中包含提供的数组和连接元素的组合。因此它有效。


41

仅供完整性考虑,并为下一个遇到此问题的人提供帮助,你通常可以使用map来实现这一操作,正如文档中所述:

map 方法按照数组中的顺序为每个元素调用一次提供的回调函数,并从结果构建一个新数组。

与之相反的是reduce方法的描述:

reduce() 方法从左到右依次将数组中的每个值(包括累加器)应用于累加器和数组的每个值(从左到右),将其缩减为单个值

(强调是我的) 因此,尽管你可以使用 reduce 来返回一个新数组,但它的一般用途是将数组缩减为单个值。

因此,对于你的代码,可以这样写:

var store = [0,1,2,3,4];

var stored = store.map(function(pV){
  console.log("pv: ", pV);
  return pV;
});

使用 reduce 函数内部的 push 或者 concat 方法尝试重构新数组,比这要复杂得多。


5
有时候,你想要执行 .filter().map() 操作,而不是使用 O(2N) 的方式,可以通过使用一次单独的 .reduce() 操作将工作量减半,保持 O(N)。 - dossy
我猜想使用ECMA的话,代码应该是这样的:store.map(it => {return it}); - fedorqui
1
@fedorqui的'SOstopharming' store.map(it => ({it})) 也可以工作。 - Jamiec
太好了!虽然我认为我会选择带有“return”的版本,因为这样对我来说更容易理解 :) - fedorqui

25

我知道这是相同的答案,但我只想展示使用reduce(),语法也可以简化为单行代码,使用ES6:

var store = [0,1,2,3,4];

var stored = store.reduce((pV,cV) => [...pV, cV], []);

console.log(stored);


4

reduce()函数在需要对每个迭代项返回多个元素的数组时非常有用:

var inputs = media.reduce((passedArray, video) => {
    passedArray.push("-i");
    passedArray.push(video.filepath);
    return passedArray;
}, []);

这里它被用于构建FFmpeg的输入数组;

[{ name: "bob", filepath: "1.mp4" }, { name: "sue", filepath: "3.mp4" }]
=> ["-i", "1.mp4", "-i", "2.mp4]

2
Array.prototype.push 方法返回数组的新长度。 Array.prototype.concat 方法将新元素插入数组并将其返回,以便可以进一步处理。这就是您需要使用 reduce 的原因:将修改后的数组传递给下一个迭代。

2
但这不是同一个数组; concat 会分配一个新的数组,这是低效的。 - Quolonel Questions

2
您可以始终使用解构:

var store = [0,1,2,3,4];

var stored = store.reduce(function(pV,cV,cI){
  console.log("pv: ", pV);
  return [...pV, cV];
},[]);

console.log(stored);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接