对象上的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]]