如何对 JavaScript 对象的值求和?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16449295/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to sum the values of a JavaScript object?
提问by Jonathan Vanasco
I'd like to sum the values of an object.
我想对一个对象的值求和。
I'm used to python where it would just be:
我已经习惯了 python 的位置:
sample = { 'a': 1 , 'b': 2 , 'c':3 };
summed = sum(sample.itervalues())
The following code works, but it's a lot of code:
以下代码有效,但代码很多:
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)
Am i missing anything obvious, or is this just the way it is?
我是否遗漏了任何明显的东西,或者这就是它的方式?
采纳答案by Sirko
You could put it all in one function:
你可以把它全部放在一个函数中:
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()
Object.keys()
和 Array.reduce()
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)}`);
But this seems to be way slower: jsperf.com
但这似乎要慢得多:jsperf.com
回答by Micha? Per?akowski
It can be as simple as that:
可以这么简单:
const sumValues = obj => Object.values(obj).reduce((a, b) => a + b);
Quoting MDN:
引用 MDN:
The
Object.values()
method returns an array of a given object's own enumerable property values, in the same order as that provided by afor...in
loop (the difference being that a for-in loop enumerates properties in the prototype chain as well).
该
Object.values()
方法返回给定对象自己的可枚举属性值的数组,其顺序与for...in
循环提供的顺序相同(区别在于 for-in 循环也枚举原型链中的属性)。
The
reduce()
method applies a function against an accumulator and each value of the array (from left-to-right) to reduce it to a single value.
该
reduce()
方法对累加器和数组的每个值(从左到右)应用一个函数以将其减少为单个值。
from Array.prototype.reduce()
on MDN
You can use this function like that:
你可以像这样使用这个函数:
sumValues({a: 4, b: 6, c: -5, d: 0}); // gives 5
Note that this code uses some ECMAScript features which are not supported by some older browsers (like IE). You might need to use Babelto compile your code.
请注意,此代码使用了一些旧浏览器(如 IE)不支持的 ECMAScript 功能。您可能需要使用Babel来编译您的代码。
回答by Leon
If you're using lodash you can do something like
如果您使用的是 lodash,则可以执行以下操作
_.sum(_.values({ 'a': 1 , 'b': 2 , 'c':3 }))
回答by Blender
A regular for
loop is pretty concise:
常规for
循环非常简洁:
var total = 0;
for (var property in object) {
total += object[property];
}
You might have to add in object.hasOwnProperty
if you modified the prototype.
object.hasOwnProperty
如果您修改了原型,则可能需要添加。
回答by jbabey
Any reason you're not just using a simple for...in
loop?
有什么理由不只是使用简单的for...in
循环?
var sample = { a: 1 , b: 2 , c:3 };
var summed = 0;
for (var key in sample) {
summed += sample[key];
};
回答by Ricardo Magalh?es
Honestly, given our "modern times" I'd go with a functional programming approach whenever possible, like so:
老实说,鉴于我们的“现代时代”,我会尽可能采用函数式编程方法,如下所示:
const sumValues = (obj) => Object.keys(obj).reduce((acc, value) => acc + obj[value], 0);
Our accumulator acc
, starting with a value of 0, is accumulating all looped values of our object. This has the added benefit of not depending on any internal or external variables; it's a constant function so it won't be accidentally overwritten... win for ES2015!
我们的 accumulator acc
,从值 0 开始,正在累积我们对象的所有循环值。这具有不依赖于任何内部或外部变量的额外好处;它是一个常量函数,所以它不会被意外覆盖...... ES2015 获胜!
回答by Krishnadas PC
Now you can make use of reduce
function and get the sum.
现在您可以使用reduce
函数并获得总和。
const object1 = { 'a': 1 , 'b': 2 , 'c':3 }
console.log(Object.values(object1).reduce((a, b) => a + b, 0));
回答by Ismael Soschinski
Use Lodash
使用 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
回答by Sudam Dissanayake
let prices = {
"apple": 100,
"banana": 300,
"orange": 250
};
let sum = 0;
for (let price of Object.values(prices)) {
sum += price;
}
alert(sum)
回答by Sudam Dissanayake
I am a bit tardy to the party, however, if you require a more robust and flexible solution then here is my contribution. If you want to sum only a specific property in a nested object/array combo, as well as perform other aggregate methods, then here is a little function I have been using on a React project:
我对聚会有点迟到,但是,如果您需要更强大和灵活的解决方案,那么这就是我的贡献。如果您只想对嵌套对象/数组组合中的特定属性求和,以及执行其他聚合方法,那么这里是我在 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;
}
It is recursive, non ES6, and it should work in most semi-modern browsers. You use it like this:
它是递归的,非 ES6,它应该可以在大多数半现代浏览器中工作。你像这样使用它:
const onlineCount = aggregateProperty(this.props.contacts, 'online', 'count');
Parameter breakdown:
参数分解:
obj= either an object or an array
property= the property within the nested objects/arrays you wish to perform the aggregate method on
aggregate= the aggregate method (sum, min, max, or count)
shallow= can either be set to true/false or a numeric value
depth= should be left null or undefined (it is used to track the subsequent recursive callbacks)
OBJ=任一物体或阵列
属性=你想要进行聚合方法的嵌套的对象/数组内的属性
骨料=聚合方法(总和,最小值,最大值,或计数)
浅=可以被设置为真/ false 或数值
depth= 应保留为 null 或未定义(用于跟踪后续的递归回调)
Shallow can be used to enhance performance if you know that you will not need to search deeply nested data. For instance if you had the following array:
如果您知道不需要搜索深度嵌套的数据,则可以使用浅层来提高性能。例如,如果您有以下数组:
[
{
id: 1,
otherData: { ... },
valueToBeTotaled: ?
},
{
id: 2,
otherData: { ... },
valueToBeTotaled: ?
},
{
id: 3,
otherData: { ... },
valueToBeTotaled: ?
},
...
]
If you wanted to avoid looping through the otherData property since the value you are going to be aggregating is not nested that deeply, you could set shallow to true.
如果您想避免循环遍历 otherData 属性,因为您要聚合的值没有嵌套那么深,您可以将浅设置为 true。