如何对 JavaScript 对象的值求和?

我想对一个对象的值求和。

我习惯了蟒蛇的位置:

sample = { 'a': 1 , 'b': 2 , 'c':3 };
summed =  sum(sample.itervalues())

下面的代码可以工作,但是代码太多了:

function obj_values(object) {
var results = [];
for (var property in object)
results.push(object[property]);
return results;
}


function list_sum( list ){
return list.reduce(function(previousValue, currentValue, index, array){
return previousValue + currentValue;
});
}


function object_values_sum( obj ){
return list_sum(obj_values(obj));
}


var sample = { a: 1 , b: 2 , c:3 };
var summed =  list_sum(obj_values(a));
var summed =  object_values_sum(a)

我是漏掉了什么明显的东西,还是就是这样?

245316 次浏览

常规的 for循环非常简洁:

var total = 0;


for (var property in object) {
total += object[property];
}

如果修改了原型,则可能必须添加 object.hasOwnProperty

为什么不使用简单的 for...in循环呢?

var sample = { a: 1 , b: 2 , c:3 };
var summed = 0;


for (var key in sample) {
summed += sample[key];
};

Http://jsfiddle.net/vzhxs/

你可以把它们放在一个函数中:

function sum( obj ) {
var sum = 0;
for( var el in obj ) {
if( obj.hasOwnProperty( el ) ) {
sum += parseFloat( obj[el] );
}
}
return sum;
}
    

var sample = { a: 1 , b: 2 , c:3 };
var summed = sum( sample );
console.log( "sum: "+summed );


为了好玩,下面是另一个使用 Object.keys()Array.reduce()的实现(浏览器支持不再是一个大问题) :

function sum(obj) {
return Object.keys(obj).reduce((sum,key)=>sum+parseFloat(obj[key]||0),0);
}
let sample = { a: 1 , b: 2 , c:3 };


console.log(`sum:${sum(sample)}`);

但这似乎要慢得多: JsPerf.com

如果你使用 loash,你可以这样做

_.sum(_.values({ 'a': 1 , 'b': 2 , 'c':3 }))

老实说,考虑到我们的“现代时代”,我会尽可能使用函数式编程方法,比如:

const sumValues = (obj) => Object.keys(obj).reduce((acc, value) => acc + obj[value], 0);

我们的累加器 acc,从0开始,累加对象的所有循环值。这样做的另一个好处是不依赖于任何内部或外部变量; 它是一个常量函数,所以它不会被意外地覆盖... ES2015获胜!

可能就是这么简单:

const sumValues = obj => Object.values(obj).reduce((a, b) => a + b, 0);

引用 MDN:

Object.values()方法返回一个给定对象自身可枚举属性值的数组,其顺序与 for...in循环提供的顺序相同(区别在于 for-in 循环也枚举原型链中的属性)。

MDN 上的 Object.values()

reduce()方法对累加器和数组的每个值(从左到右)应用一个函数,以将其减少为单个值。

MDN 上的 Array.prototype.reduce()

你可以这样使用这个函数:

sumValues({a: 4, b: 6, c: -5, d: 0}); // gives 5

请注意,这段代码使用了一些 ECMAScript 特性,而这些特性是一些较老的浏览器(如 IE)所不支持的。您可能需要使用 巴别塔来编译代码。

我在试图解决一个类似的问题时从@jbabey 得到了这个解决方案。稍微修改一下,我就做对了。在我的示例中,对象键是数字(489)和字符串(“489”)。因此,为了解决这个问题,每个键都是 parse。下列守则适用:

var array = {"nR": 22, "nH": 7, "totB": "2761", "nSR": 16, "htRb": "91981"}
var parskey = 0;
for (var key in array) {
parskey = parseInt(array[key]);
sum += parskey;
};
return(sum);

我有点迟到,但是,如果你需要一个更强大和灵活的解决方案,那么这里是我的贡献。如果你想在嵌套的对象/数组组合中只求和一个特定的属性,以及执行其他聚合方法,那么这里有一个我在 React 项目中使用的小函数:

var aggregateProperty = function(obj, property, aggregate, shallow, depth) {
//return aggregated value of a specific property within an object (or array of objects..)


if ((typeof obj !== 'object' && typeof obj !== 'array') || !property) {
return;
}


obj = JSON.parse(JSON.stringify(obj)); //an ugly way of copying the data object instead of pointing to its reference (so the original data remains unaffected)
const validAggregates = [ 'sum', 'min', 'max', 'count' ];
aggregate = (validAggregates.indexOf(aggregate.toLowerCase()) !== -1 ? aggregate.toLowerCase() : 'sum'); //default to sum


//default to false (if true, only searches (n) levels deep ignoring deeply nested data)
if (shallow === true) {
shallow = 2;
} else if (isNaN(shallow) || shallow < 2) {
shallow = false;
}


if (isNaN(depth)) {
depth = 1; //how far down the rabbit hole have we travelled?
}


var value = ((aggregate == 'min' || aggregate == 'max') ? null : 0);
for (var prop in obj) {
if (!obj.hasOwnProperty(prop)) {
continue;
}


var propValue = obj[prop];
var nested = (typeof propValue === 'object' || typeof propValue === 'array');
if (nested) {
//the property is an object or an array


if (prop == property && aggregate == 'count') {
value++;
}


if (shallow === false || depth < shallow) {
propValue = aggregateProperty(propValue, property, aggregate, shallow, depth+1); //recursively aggregate nested objects and arrays
} else {
continue; //skip this property
}
}


//aggregate the properties value based on the selected aggregation method
if ((prop == property || nested) && propValue) {
switch(aggregate) {
case 'sum':
if (!isNaN(propValue)) {
value += propValue;
}
break;
case 'min':
if ((propValue < value) || !value) {
value = propValue;
}
break;
case 'max':
if ((propValue > value) || !value) {
value = propValue;
}
break;
case 'count':
if (propValue) {
if (nested) {
value += propValue;
} else {
value++;
}
}
break;
}
}
}


return value;
}

它是递归的,非 ES6,并且它应该可以在大多数半现代的浏览器中工作:

const onlineCount = aggregateProperty(this.props.contacts, 'online', 'count');

参数分解:

Obj = 对象或数组
Property = 希望对其执行聚合方法的嵌套对象/数组中的属性
聚合 = 聚合方法(sum,min,max,or count)
肤浅 = 既可以设置为 true/false,也可以设置为数值
Deep = 应为 null 或未定义(用于跟踪后续的递归回调) < br/>

如果您知道不需要搜索深度嵌套的数据,则可以使用 Shallow 来提高性能。例如,如果您有以下数组:

[
{
id: 1,
otherData: { ... },
valueToBeTotaled: ?
},
{
id: 2,
otherData: { ... },
valueToBeTotaled: ?
},
{
id: 3,
otherData: { ... },
valueToBeTotaled: ?
},
...
]

如果希望避免通过 other Data 属性进行循环,因为要聚合的值没有嵌套得那么深,那么可以将肤浅设置为 true。

一个 Ramda一行程序:

import {
compose,
sum,
values,
} from 'ramda'


export const sumValues = compose(sum, values);

用途: const summed = sumValues({ 'a': 1 , 'b': 2 , 'c':3 });

现在您可以利用 reduce函数得到和。

const object1 = { 'a': 1 , 'b': 2 , 'c':3 }


console.log(Object.values(object1).reduce((a, b) => a + b, 0));

使用 Lodash

 import _ from 'Lodash';
 

var object_array = [{a: 1, b: 2, c: 3}, {a: 4, b: 5, c: 6}];
 

return _.sumBy(object_array, 'c')
 

// return => 9

let prices = {
"apple": 100,
"banana": 300,
"orange": 250
};


let sum = 0;
for (let price of Object.values(prices)) {
sum += price;
}


alert(sum)

我们可以使用 进去关键字迭代对象,并且可以执行任何算术运算。

// input
const sample = {
'a': 1,
'b': 2,
'c': 3
};


// var
let sum = 0;


// object iteration
for (key in sample) {
//sum
sum += (+sample[key]);
}
// result
console.log("sum:=>", sum);

通过解析 Integer,将字符串格式转换为整数,并对对象键值进行求和

var obj = {
pay: 22
};
obj.pay;
console.log(obj.pay);
var x = parseInt(obj.pay);
console.log(x + 20);

一个简单的解决方案是使用 for. . in 循环来求和。

function findSum(obj){
let sum = 0;
for(property in obj){
sum += obj[property];
}
return sum;
}




var sample = { a: 1 , b: 2 , c:3 };
console.log(findSum(sample));

function myFunction(a) { return Object.values(a).reduce((sum, cur) => sum + cur, 0); }

function totalAmountAdjectives(obj) {
let sum = 0;
for(let el in obj) {
sum += el.length;
}
return sum;
}
console.log(totalAmountAdjectives({ a: "apple" }))

一个简单而干净的打字解决方案:

const sample = { a: 1, b: 2, c: 3 };
const totalSample = Object.values(sample).reduce(
(total: number, currentElement: number) => total + currentElement
);
console.log(totalSample);

祝你好运!