Подтвердить что ты не робот

Как суммировать значения объекта JavaScript?

Я хотел бы суммировать значения объекта.

Я использую python, где это будет просто:

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)

Мне не хватает ничего очевидного или это так, как есть?

4b9b3361

Ответ 1

Вы можете поместить все это в одну функцию:

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

Ответ 2

Это может быть так просто:

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

Цитирование MDN:

Метод Object.values() возвращает массив соответствующих значений свойств Object.values() объекта в том же порядке, что и for...in цикла for...in (разница заключается в том, что цикл for-in перечисляет свойства в цепочке прототипов также).

из Object.values() в MDN

Метод reduce() применяет функцию к аккумулятору и каждому значению массива (слева направо), чтобы уменьшить его до одного значения.

из Array.prototype.reduce() на MDN

Вы можете использовать эту функцию следующим образом:

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

Обратите внимание, что в этом коде используются некоторые функции ECMAScript, которые не поддерживаются некоторыми более старыми браузерами (например, IE). Возможно, вам придется использовать Babel для компиляции вашего кода.

Ответ 3

Регулярный цикл for довольно краток:

var total = 0;

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

Возможно, вам придется добавить object.hasOwnProperty, если вы изменили прототип.

Ответ 4

Если вы используете lodash, вы можете сделать что-то вроде

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

Ответ 5

Любая причина, по которой вы не просто используете простой цикл 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/

Ответ 6

Честно говоря, учитывая наши "современные времена", я по возможности использовал бы функциональный программный подход, например:

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

Наш аккумулятор acc, начиная со значения 0, накапливает все зацикленные значения нашего объекта. Это имеет дополнительное преимущество независимо от каких-либо внутренних или внешних переменных; это постоянная функция, поэтому она не будет случайно перезаписана... выиграть для ES2015!

Ответ 7

Теперь вы можете использовать reduce функцию и получить сумму.

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

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

Ответ 8

Я немного опоздал на вечеринку, однако, если вам требуется более надежное и гибкое решение, то вот мой вклад. Если вы хотите суммировать только определенное свойство во вложенном комбайне object/array, а также выполнять другие агрегированные методы, то вот небольшая функция, которую я использовал в проекте 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= либо объект, либо массив
свойство= свойство внутри вложенных объектов/массивов, которые вы хотите выполнить агрегированный метод на
агрегат= совокупный метод (сумма, мин, макс или количество)
мелкий= может быть установлен как true/false или числовое значение
глубина= должна быть оставлена ​​нулевой или undefined (она используется для отслеживания последующих рекурсивных обратных вызовов)

Неглубокие можно использовать для повышения производительности, если вы знаете, что вам не нужно искать глубоко вложенные данные. Например, если у вас был следующий массив:

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

Если вы хотите избежать циклического перехода через свойство otherData, так как значение, которое вы собираетесь агрегировать, не вложено настолько глубоко, что вы можете установить неглубокое значение true.

Ответ 9

Я столкнулся с этим решением от @jbabey, пытаясь решить подобную проблему. С небольшим изменением я понял все правильно. В моем случае ключом объекта являются числа (489) и строки ( "489" ). Следовательно, чтобы решить это, каждый ключ разбирается. Работает следующий код:

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

Ответ 10

Рампа один лайнер:

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

export const sumValues = compose(sum, values);

Использовать: const summed = sumValues({ 'a': 1, 'b': 2, 'c':3 });

Ответ 11

Используйте 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