Я хочу просуммировать значения объекта.
Я привык к 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)
Я упускаю что-то очевидное, или это так?
javascript
object
javascript-objects
Джонатан Ванаско
источник
источник
Object.keys().reduce
выглядит намного элегантнее, он на 60% медленнее.Это может быть так просто:
const sumValues = obj => Object.values(obj).reduce((a, b) => a + b);
Цитата MDN:
от
Object.values()
MDNот
Array.prototype.reduce()
MDNВы можете использовать эту функцию так:
sumValues({a: 4, b: 6, c: -5, d: 0}); // gives 5
Обратите внимание, что в этом коде используются некоторые функции ECMAScript, которые не поддерживаются некоторыми старыми браузерами (например, IE). Возможно, вам понадобится использовать Babel для компиляции вашего кода.
источник
Object.values()
, который будет polyfilled сfor
петлей на любом браузере , кроме Firefox. Даже без полифилаfor
для меня это в 4 раза медленнее, чем обычный цикл.Object.values()
до этого времени.reduce
кажется немного более надежной. Вы специально пропустили парсинг?Object.values()
поддерживается всеми современными браузерами .Если вы используете lodash, вы можете сделать что-то вроде
_.sum(_.values({ 'a': 1 , 'b': 2 , 'c':3 }))
источник
Обычный
for
цикл довольно лаконичен:var total = 0; for (var property in object) { total += object[property]; }
Возможно, вам придется добавить,
object.hasOwnProperty
если вы изменили прототип.источник
Честно говоря, учитывая наше "современное время", я бы по возможности использовал подход функционального программирования, например:
const sumValues = (obj) => Object.keys(obj).reduce((acc, value) => acc + obj[value], 0);
Наш аккумулятор
acc
, начиная со значения 0, накапливает все зацикленные значения нашего объекта. Это дает дополнительное преимущество: он не зависит от каких-либо внутренних или внешних переменных; это постоянная функция, поэтому она не будет случайно перезаписана ... победа для ES2015!источник
По какой причине вы не используете простой
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/
источник
Теперь вы можете воспользоваться
reduce
функцией и получить сумму.const object1 = { 'a': 1 , 'b': 2 , 'c':3 } console.log(Object.values(object1).reduce((a, b) => a + b, 0));
источник
Я немного опоздал с вечеринкой, однако, если вам требуется более надежное и гибкое решение, вот мой вклад. Если вы хотите суммировать только определенное свойство во вложенной комбинации объект / массив, а также выполнять другие агрегированные методы, то вот небольшая функция, которую я использовал в проекте 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 = либо объект, либо
свойство массива = свойство внутри вложенных объектов / массивов, которое вы хотите выполнить агрегатным методом для
агрегата = агрегатный метод (сумма, мин., макс. или счетчик)
shallow = может иметь значение true / false или числовое значение
depth = следует оставить null или undefined (используется для отслеживания последующих рекурсивных обратных вызовов)
Shallow можно использовать для повышения производительности, если вы знаете, что вам не нужно искать глубоко вложенные данные. Например, если у вас был следующий массив:
[ { id: 1, otherData: { ... }, valueToBeTotaled: ? }, { id: 2, otherData: { ... }, valueToBeTotaled: ? }, { id: 3, otherData: { ... }, valueToBeTotaled: ? }, ... ]
Если вы хотите избежать цикла по свойству otherData, поскольку значение, которое вы собираетесь агрегировать, не вложено так глубоко, вы можете установить shallow на true.
источник
Используйте 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)
источник
Я столкнулся с этим решением от @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);
источник
Ramda один лайнер:
import { compose, sum, values, } from 'ramda' export const sumValues = compose(sum, values);
Использование:
const summed = sumValues({ 'a': 1 , 'b': 2 , 'c':3 });
источник
Мы можем перебирать объект, используя ключевое слово in, и можем выполнять любую арифметическую операцию.
// 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);
источник