对象上的Javascript reduce()

有很好的数组方法reduce()从数组中获取一个值。 例:

 [0,1,2,3,4].reduce(function(previousValue, currentValue, index, array){ return previousValue + currentValue; }); 

什么是达到与对象相同的最佳方式? 我想这样做:

 { a: {value:1}, b: {value:2}, c: {value:3} }.reduce(function(previous, current, index, array){ return previous.value + current.value; }); 

但是,Object似乎没有实现任何reduce()方法。

一种select是reduce keys()

 var o = { a: {value:1}, b: {value:2}, c: {value:3} }; Object.keys(o).reduce(function (previous, key) { return previous + o[key].value; }, 0); 

有了这个,你需要指定一个初始值,或者第一轮将是'a' + 2

如果你想把结果作为一个Object( { value: ... } ),你必须每次初始化和返回对象:

 Object.keys(o).reduce(function (previous, key) { previous.value += o[key].value; return previous; }, { value: 0 }); 

首先,你不太清楚减less的是以前的价值。

在你的伪代码中,你已经return previous.value + current.value ,因此previous值将是下一次调用的一个数字,而不是一个对象。

其次, reduce是一个数组方法,而不是对象的方法,当迭代对象的属性时,不能依赖顺序(请参阅: https : //developer.mozilla.org/en-US/docs /JavaScript/Reference/Statements/for…in ,这也适用于Object.keys ); 所以我不确定是否应用reduce对象是有道理的。

但是,如果顺序不重要,可以有:

 Object.keys(obj).reduce(function(sum, key) { return sum + obj[key].value; }, 0); 

或者你可以只映射对象的值:

 Object.keys(obj).map(function(key) { return this[key].value }, obj).reduce(function (previous, current) { return previous + current; }); 

在ES6中使用胖箭头函数的语法(已经在Firefox Nightly中),你可以缩小一点:

 Object.keys(obj).map(key => obj[key].value).reduce((previous, current) => previous + current); 

ES6实现: Object.entries()

 const o = { a: {value: 1}, b: {value: 2}, c: {value: 3} }; const total = Object.entries(o).reduce(function (total, pair) { const [key, value] = pair; return total + value; }, 0); 

扩展Object.prototype。

 Object.prototype.reduce = function( reduceCallback, initialValue ) { var obj = this, keys = Object.keys( obj ); return keys.reduce( function( prevVal, item, idx, arr ) { return reduceCallback( prevVal, item, obj[item], obj ); }, initialValue ); }; 

使用示例。

 var dataset = { key1 : 'value1', key2 : 'value2', key3 : 'value3' }; function reduceFn( prevVal, key, val, obj ) { return prevVal + key + ' : ' + val + '; '; } console.log( dataset.reduce( reduceFn, 'initialValue' ) ); 'Output' == 'initialValue; key1 : value1; key2 : value2; key3 : value3; '. 

你好,伙计! 😉

在这种情况下你真正想要的是Object.values 。 考虑到这一点,下面是一个简洁的ES6实现:

 add = { a: {value:1}, b: {value:2}, c: {value:3} } total = Object.values(add).reduce((t, n) => t + n.value, 0) console.log(total) // 6 

或者干脆:

 add = { a: 1, b: 2, c: 3 } total = Object.values(add).reduce((t, n) => t + n) console.log(total) // 6 

这不是很难实现你自己:

 function reduceObj(obj, callback, initial) { "use strict"; var key, lastvalue, firstIteration = true; if (typeof callback !== 'function') { throw new TypeError(callback + 'is not a function'); } if (arguments.length > 2) { // initial value set firstIteration = false; lastvalue = initial; } for (key in obj) { if (!obj.hasOwnProperty(key)) continue; if (firstIteration) firstIteration = false; lastvalue = obj[key]; continue; } lastvalue = callback(lastvalue, obj[key], key, obj); } if (firstIteration) { throw new TypeError('Reduce of empty object with no initial value'); } return lastvalue; } 

在行动:

 var o = {a: {value:1}, b: {value:2}, c: {value:3}}; reduceObj(o, function(prev, curr) { prev.value += cur.value; return prev;}, {value:0}); reduceObj(o, function(prev, curr) { return {value: prev.value + curr.value};}); // both == { value: 6 }; reduceObj(o, function(prev, curr) { return prev + curr.value; }, 0); // == 6 

您也可以将其添加到对象原型中:

 if (typeof Object.prototype.reduce !== 'function') { Object.prototype.reduce = function(callback, initial) { "use strict"; var args = Array.prototype.slice(arguments); args.unshift(this); return reduceObj.apply(null, args); } } 

1:

 [{value:5}, {value:10}].reduce((previousValue, currentValue) => { return {value: previousValue.value + currentValue.value}}) >> Object {value: 15} 

2:

 [{value:5}, {value:10}].map(item => item.value).reduce((previousValue, currentValue) => {return previousValue + currentValue }) >> 15 

3:

 [{value:5}, {value:10}].reduce(function (previousValue, currentValue) { return {value: previousValue.value + currentValue.value}; }) >> Object {value: 15} 

如果你可以使用一个数组,那么使用一个数组,数组的长度和顺序是它的一半。

 function reducer(obj, fun, temp){ if(typeof fun=== 'function'){ if(temp== undefined) temp= ''; for(var p in obj){ if(obj.hasOwnProperty(p)){ temp= fun(obj[p], temp, p, obj); } } } return temp; } var O={a:{value:1},b:{value:2},c:{value:3}} reducer(O, function(a, b){return a.value+b;},0); 

/ *返回值:(数字)6 * /

您可以使用一个生成器expression式(在所有浏览器中支持多年,现在在Node中)来获取您可以减less的列表中的键值对:

 >>> a = {"b": 3} Object { b=3} >>> [[i, a[i]] for (i in a) if (a.hasOwnProperty(i))] [["b", 3]]