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 = 3
, b = {x:2}
返回NaN
一个数字字面3
不(通常)有一个名为x
的属性,所以它是undefined
并且undefined + bx
返回NaN
和NaN + <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源代码