Eu gostaria de somar os valores de um objeto.
Estou acostumado a fazer python onde seria apenas:
sample = { 'a': 1 , 'b': 2 , 'c':3 };
summed = sum(sample.itervalues())
O código a seguir funciona, mas é muito código:
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)
Estou perdendo algo óbvio ou é assim que as coisas são?
javascript
object
javascript-objects
Jonathan Vanasco
fonte
fonte
Object.keys().reduce
pareça muito mais elegante, é 60% mais lento.Pode ser tão simples quanto isso:
const sumValues = obj => Object.values(obj).reduce((a, b) => a + b);
Citando MDN:
de
Object.values()
em MDNde
Array.prototype.reduce()
em MDNVocê pode usar essa função assim:
sumValues({a: 4, b: 6, c: -5, d: 0}); // gives 5
Observe que este código usa alguns recursos ECMAScript que não são suportados por alguns navegadores mais antigos (como o IE). Você pode precisar usar o Babel para compilar seu código.
fonte
Object.values()
, que será preenchida com umfor
loop em todos os navegadores além do Firefox. Mesmo sem um polyfill, é 4x mais lento do que umfor
loop normal para mim.Object.values()
até esse momento.reduce
parece um pouco mais infalível. Você omitiu a análise de propósito?Object.values()
é compatível com todos os navegadores modernos .Se você estiver usando lodash, pode fazer algo como
_.sum(_.values({ 'a': 1 , 'b': 2 , 'c':3 }))
fonte
Um
for
loop regular é bastante conciso:var total = 0; for (var property in object) { total += object[property]; }
Você pode ter que adicionar
object.hasOwnProperty
se você modificou o protótipo.fonte
Honestamente, devido aos nossos "tempos modernos", eu escolheria uma abordagem de programação funcional sempre que possível, assim:
const sumValues = (obj) => Object.keys(obj).reduce((acc, value) => acc + obj[value], 0);
Nosso acumulador
acc
, começando com um valor de 0, está acumulando todos os valores em loop de nosso objeto. Isso tem o benefício adicional de não depender de nenhuma variável interna ou externa; é uma função constante, então não será sobrescrito acidentalmente ... vença para ES2015!fonte
Alguma razão para você não estar usando apenas um
for...in
loop simples ?var sample = { a: 1 , b: 2 , c:3 }; var summed = 0; for (var key in sample) { summed += sample[key]; };
http://jsfiddle.net/vZhXs/
fonte
Agora você pode usar a
reduce
função e obter a soma.const object1 = { 'a': 1 , 'b': 2 , 'c':3 } console.log(Object.values(object1).reduce((a, b) => a + b, 0));
fonte
Estou um pouco atrasado para a festa, no entanto, se você precisa de uma solução mais robusta e flexível, então aqui está minha contribuição. Se você deseja somar apenas uma propriedade específica em uma combinação de objeto / matriz aninhada, bem como realizar outros métodos de agregação, aqui está uma pequena função que venho usando em um projeto 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; }
É recursivo, não ES6, e deve funcionar na maioria dos navegadores semimodernos. Você o usa assim:
const onlineCount = aggregateProperty(this.props.contacts, 'online', 'count');
Repartição de parâmetros:
obj = um objeto ou uma
propriedade de matriz = a propriedade dentro dos objetos / matrizes aninhados que você deseja executar o método
agregado em agregação = o método agregado (soma, mínimo, máximo ou contagem)
raso = pode ser definido como verdadeiro / false ou um valor numérico
depth = deve ser deixado nulo ou indefinido (é usado para rastrear os retornos de chamada recursivos subsequentes)
Raso pode ser usado para melhorar o desempenho se você souber que não precisará pesquisar dados profundamente aninhados. Por exemplo, se você tivesse a seguinte matriz:
[ { id: 1, otherData: { ... }, valueToBeTotaled: ? }, { id: 2, otherData: { ... }, valueToBeTotaled: ? }, { id: 3, otherData: { ... }, valueToBeTotaled: ? }, ... ]
Se você quiser evitar o loop através da propriedade otherData, já que o valor que você vai agregar não está aninhado tão profundamente, você pode definir raso como verdadeiro.
fonte
Use 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
fonte
let prices = { "apple": 100, "banana": 300, "orange": 250 }; let sum = 0; for (let price of Object.values(prices)) { sum += price; } alert(sum)
fonte
Encontrei essa solução com @jbabey ao tentar resolver um problema semelhante. Com uma pequena modificação, acertei. No meu caso, as chaves do objeto são números (489) e strings ("489"). Portanto, para resolver isso, cada chave é analisada. O seguinte código funciona:
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);
fonte
Um ramda one liner:
import { compose, sum, values, } from 'ramda' export const sumValues = compose(sum, values);
Usar:
const summed = sumValues({ 'a': 1 , 'b': 2 , 'c':3 });
fonte
Podemos interagir objeto usando a palavra-chave e pode executar qualquer operação aritmética.
// 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);
fonte
Some o valor da chave do objeto por parse Integer. Converter o formato da string em inteiro e somar os valores
var obj = { pay: 22 }; obj.pay; console.log(obj.pay); var x = parseInt(obj.pay); console.log(x + 20);
fonte