How to sum the values of a JavaScript object?

后端 未结 14 683
梦如初夏
梦如初夏 2020-11-27 04:03

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(sampl         


        
相关标签:
14条回答
  • 2020-11-27 04:07

    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/

    0 讨论(0)
  • 2020-11-27 04:07

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

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

    0 讨论(0)
  • 2020-11-27 04:09

    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);
    
    0 讨论(0)
  • 2020-11-27 04:10

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

    0 讨论(0)
  • 2020-11-27 04:11

    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.

    0 讨论(0)
  • 2020-11-27 04:17

    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.

    0 讨论(0)
提交回复
热议问题