JavaScript减less对象的数组

假设我想对arr每个元素进行求和。

 arr = [{x:1},{x:2},{x:4}] arr.reduce(function(a,b){return ax + bx}) >> NaN 

我有理由相信斧头在某个时刻是不确定的。

以下工作正常

 arr = [1,2,4] arr.reduce(function(a,b){return a + b}) >> 7 

第一个例子我做错了什么?

在第一次迭代之后,你要返回一个数字,然后试图让它的属性x添加到undefined的下一个对象,以及在NaN涉及undefined结果的math。

尝试返回一个包含x属性的对象,其中包含参数x属性的总和:

 var arr = [{x:1},{x:2},{x:4}]; arr.reduce(function (a, b) { return {x: ax + bx}; // returns object with property x }) // ES6 arr.reduce((a, b) => ({x: ax + bx})); // -> {x: 7} 

解释添加评论:

[].reduce的每次迭代的返回值在下一次迭代中用作variables。

迭代1: a = {x:1}b = {x:2}{x: 3}分配给a in Iteration 2

迭代2: a = {x:3}b = {x:4}

你的例子的问题是,你正在返回一个数字文字。

 function (a, b) { return ax + bx; // returns number literal } 

迭代1: a = {x:1}b = {x:2}// returns 3在下一次迭代中// returns 3

迭代2: a = 3b = {x:2}返回NaN

一个数字字面3不(通常)有一个名为x的属性,所以它是undefined并且undefined + bx返回NaNNaN + <anything>总是NaN

澄清 :我更喜欢我的方法在这个线程中的其他顶部的答案,因为我不同意传递一个可选的参数来减less一个魔术数字来获得一个数字原语是更清洁的想法。 这可能会导致更less的行被写入,但它是不太可读的。

一个更简单的方法是通过提供一个初始值:

 var arr = [{x:1}, {x:2}, {x:4}]; arr.reduce(function (acc, obj) { return acc + obj.x; }, 0); // 7 

第一次调用匿名函数时,它被调用(0, {x: 1})并返回0 + 1 = 1 。 下一次,它被调用(1, {x: 2})并返回1 + 2 = 3 。 然后用(3, {x: 4})调用,最后返回7

其他人已经回答了这个问题,但我想我会用另一种方法折腾。 你可以把一个地图(从ax到x)和reduce(添加x)组合起来,而不是直接去求和ax:

 arr = [{x:1},{x:2},{x:4}] arr.map(function(a) {return ax;}) .reduce(function(a,b) {return a + b;}); 

不可否认,这可能会稍微慢一些,但我认为值得一提的是它。

在ES6这只是一个简短的一行

arr.reduce( (sum,cur) => sum+cur.x , 0)

这感觉像Ruby。 无论如何,关键是设置初始值。 返回值成为下一次迭代的第一个参数。

第一遍, sum为零。 cur是数组中的第一个值,一个对象。 所以我们访问x属性。 我们添加这个数字来sum并返回它。

下一次迭代,同样的事情。 sum现在是最后返回的值,我们添加下一个项目等等。

如果我们没有在最后设置0 ,那么第一个迭代sum将是一个对象,我们将编写逻辑来处理一个对象。 我们还必须返回一个对象,因为下一个迭代被设置为处理一个对象。

希望这可以帮助!

为了使已经指出的东西forms化,reducer是一个变形,它带有两个可能是相同types的参数,并返回一个匹配第一个参数的types。

 function reducer (accumulator: X, currentValue: Y): X { } 

这意味着减速器的本体需要将电stream值和accumulator的当前值转换为新accumulator的值。

这在添加时是直接的,因为累加器和元素值恰好是相同的types(但是用于不同的目的)。

 [1, 2, 3].reduce((x, y) => x + y); 

这只是因为他们都是数字。

 [{ age: 5 }, { age: 2 }, { age: 8 }] .reduce((total, thing) => total + thing.age, 0); 

现在我们给聚合器一个初始值。 在绝大多数情况下,起始值应该是您期望聚合器的types(您期望作为最终值出现的types)。 虽然你不是被迫这样做(而不应该这样做),但要记住这一点很重要。

一旦你知道了,你可以写出有意义的减less其他n:1关系的问题。

删除重复的单词:

 const skipIfAlreadyFound = (words, word) => words.includes(word) ? words : words.concat(word); const deduplicatedWords = aBunchOfWords.reduce(skipIfAlreadyFound, []); 

提供find的所有单词的计数:

 const incrementWordCount = (counts, word) => { counts[word] = (counts[word] || 0) + 1; return counts; }; const wordCounts = words.reduce(incrementWordCount, { }); 

将一个数组的数组,减less到一个单一的平面数组:

 const concat = (a, b) => a.concat(b); const numbers = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ].reduce(concat, []); 

任何时候你想从一系列的东西,到一个单一的值不匹配1:1,减less是你可能会考虑的东西。

实际上,map和filter都可以实现为reduce:

 const map = (transform, array) => array.reduce((list, el) => list.concat(transform(el)), []); const filter = (predicate, array) => array.reduce( (list, el) => predicate(el) ? list.concat(el) : list, [] ); 

我希望这为如何使用reduce提供了一些进一步的背景。

除此之外,我还没有涉及的是,当有一个期望input和输出types是专门用来dynamic的,因为数组元素是函数:

 const compose = (...fns) => x => fns.reduceRight((x, f) => f(x), x); const hgfx = h(g(f(x))); const hgf = compose(h, g, f); const hgfy = hgf(y); const hgfz = hgf(z); 

在减less的每一步中,您都不会返回一个新的{x:???}对象。 所以你要么做:

 arr = [{x:1},{x:2},{x:4}] arr.reduce(function(a,b){return a + bx}) 

或者你需要做的

 arr = [{x:1},{x:2},{x:4}] arr.reduce(function(a,b){return {x: ax + bx}; }) 

reduce函数迭代一个集合

 arr = [{x:1},{x:2},{x:4}] // is a collection arr.reduce(function(a,b){return ax + bx}) 

转化为:

 arr.reduce( //for each index in the collection, this callback function is called function ( a, //a = accumulator ,during each callback , value of accumulator is passed inside the variable "a" b, //currentValue , for ex currentValue is {x:1} in 1st callback currentIndex, array ) { return ax + bx; }, accumulator // this is returned at the end of arr.reduce call //accumulator = returned value ie return ax + bx in each callback. ); 

在每个索引callback期间,variables“accumulator”的值被传入callback函数中的“a”参数。 如果我们不初始化“累加器”,其值将不确定。 调用undefined.x会给你错误。

为了解决这个问题,如上面Casey的答案所示,初始化值为0的 “累加器”。

为了理解“reduce”函数的input,我build议你看一下这个函数的源代码。 Lodash库具有与ES6中的“减less”function完全相同的减lessfunction。

这里是链接: 减less源代码