Hur summerar man värdena i ett JavaScript-objekt?
Jag skulle vilja summera värdena i ett objekt.
Jag är van vid Python där det bara skulle vara:
sample = { 'a': 1 , 'b': 2 , 'c':3 };
summed = sum(sample.itervalues())
Följande kod fungerar, men det är mycket kod:
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)
Saknar jag något uppenbart, eller är det bara så det är?
Svar #1
Det kan vara så enkelt:
const sumValues = obj => Object.values(obj).reduce((a, b) => a + b, 0);
Citerar MDN:
Metoden
Object.values()returnerar en array av ett givet objekts egna uppräkningsbara egenskapsvärden, i samma ordning som den som tillhandahålls av enfor...in-slinga (skillnaden är att en for-in-slinga även uppräknar egenskaper i prototypkedjan).
från Object.values() på MDN
Metoden
reduce()tillämpar en funktion på en ackumulator och varje värde i arrayen (från vänster till höger) för att minska den till ett enda värde.
från Array.prototype.reduce() på MDN
Du kan använda den här funktionen på det här sättet:
sumValues({a: 4, b: 6, c: -5, d: 0}); // gives 5
Observera att denna kod använder vissa ECMAScript-funktioner som inte stöds av vissa äldre webbläsare (som IE). Du kan behöva använda Babel för att kompilera din kod.
Svar #2
Du skulle kunna lägga allt i en funktion:
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 );För skojs skull här är en annan implementation som använder
Object.keys() och Array.reduce() (webbläsarstöd borde inte vara ett stort problem längre):function sum(obj) {
return Object.keys(obj).reduce((sum,key)=>sum+parseFloat(obj[key]||0),0);
}
let sample = { a: 1 , b: 2 , c:3 };
console.log(`sum:${sum(sample)}`);Men detta verkar vara mycket långsammare: jsperf.com
Svar #3
Om du använder lodash kan du göra något som
_.sum(_.values({ 'a': 1 , 'b': 2 , 'c':3 }))
Svar #4
Nu kan du använda reduce-funktionen och få summan.
const object1 = { 'a': 1 , 'b': 2 , 'c':3 }
console.log(Object.values(object1).reduce((a, b) => a + b, 0));Svar #5
En vanlig for-loop är ganska kortfattad:
var total = 0;
for (var property in object) {
total += object[property];
}
Du kan behöva lägga till object.hasOwnProperty om du har ändrat prototypen.
Svar #6
Ärligt talat, med tanke på vår "moderna tid" skulle jag välja ett funktionellt programmeringssätt när det är möjligt, så här:
const sumValues = (obj) => Object.keys(obj).reduce((acc, value) => acc + obj[value], 0);
Vår ackumulator acc, som börjar med värdet 0, ackumulerar alla loopade värden av vårt objekt. Detta har den ytterligare fördelen att den inte är beroende av några interna eller externa variabler; det är en konstant funktion så den kommer inte att råka skrivas över... vinst för ES2015!
Svar #7
Finns det någon anledning till att du inte bara använder en enkel 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/
