[javascript] How to sum the values of a JavaScript object?

I'd like to sum the values of an object.

I'm used to python where it would just be:

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?

This question is related to javascript object javascript-objects

The answer is


A ramda one liner:

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

export const sumValues = compose(sum, values);

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


A regular for loop is pretty concise:

var total = 0;

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

You might have to add in object.hasOwnProperty if you modified the prototype.


Any reason you're not just using a simple for...in loop?

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

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

http://jsfiddle.net/vZhXs/


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:

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:

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)

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.


It can be as simple as that:

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

Quoting 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 a for...in loop (the difference being that a for-in loop enumerates properties in the prototype chain as well).

from Object.values() on MDN

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.

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 Babel to compile your code.


Use Lodash

_x000D_
_x000D_
 import _ from 'Lodash';_x000D_
 _x000D_
 var object_array = [{a: 1, b: 2, c: 3}, {a: 4, b: 5, c: 6}];_x000D_
 _x000D_
 return _.sumBy(object_array, 'c')_x000D_
 _x000D_
 // return => 9
_x000D_
_x000D_
_x000D_


_x000D_
_x000D_
let prices = {_x000D_
  "apple": 100,_x000D_
  "banana": 300,_x000D_
  "orange": 250_x000D_
};_x000D_
_x000D_
let sum = 0;_x000D_
for (let price of Object.values(prices)) {_x000D_
  sum += price;_x000D_
}_x000D_
_x000D_
alert(sum)
_x000D_
_x000D_
_x000D_


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!


Sum the object key value by parse Integer. Converting string format to integer and summing the values

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


I came across this solution from @jbabey while trying to solve a similar problem. With a little modification, I got it right. In my case, the object keys are numbers (489) and strings ("489"). Hence to solve this, each key is parse. The following code works:

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);

Now you can make use of reduce function and get the sum.

_x000D_
_x000D_
const object1 = { 'a': 1 , 'b': 2 , 'c':3 }_x000D_
_x000D_
console.log(Object.values(object1).reduce((a, b) => a + b, 0));
_x000D_
_x000D_
_x000D_


We can iterate object using in keyword and can perform any arithmetic operation.

_x000D_
_x000D_
// 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);
_x000D_
_x000D_
_x000D_


If you're using lodash you can do something like

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

Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to object

How to update an "array of objects" with Firestore? how to remove json object key and value.? Cast object to interface in TypeScript Angular 4 default radio button checked by default How to use Object.values with typescript? How to map an array of objects in React How to group an array of objects by key push object into array Add property to an array of objects access key and value of object using *ngFor

Examples related to javascript-objects

Cannot read property 'style' of undefined -- Uncaught Type Error Is this a good way to clone an object in ES6? What’s the difference between “{}” and “[]” while declaring a JavaScript array? Comparing two arrays of objects, and exclude the elements who match values into new array in JS Converting JavaScript object with numeric keys into array From an array of objects, extract value of a property as array How to copy JavaScript object to new variable NOT by reference? Remove property for all objects in array Using curl POST with variables defined in bash script functions How to sum the values of a JavaScript object?