Best way to sum property value in array

I have something like this:

$scope.traveler = [ { description: 'Senior', Amount: 50}, { description: 'Senior', Amount: 50}, { description: 'Adult', Amount: 75}, { description: 'Child', Amount: 35}, { description: 'Infant', Amount: 25 }, ]; 

Now, to get the total number of this array, I am doing something like this:

 $scope.totalAmount = function(){ var total = 0; for (var i = 0; i < $scope.traveler.length; i++) { total = total + $scope.traveler[i].Amount; } return total; } 

This is easy when there is only one array, but I have other arrays with a different property name that I would like to summarize.

I would be happy if I could do something like this:

 $scope.traveler.Sum({ Amount }); 

But I donโ€™t know how to get through this so that I can use it in the future, like this:

 $scope.someArray.Sum({ someProperty }); 

Answer

I decided to use the @ gruff-bunny sentence to avoid prototyping the native object (Array)

I just made a small modification to his answer, checking the array and the sum value is not null, this is my last implementation:

 $scope.sum = function (items, prop) { if (items == null) { return 0; } return items.reduce(function (a, b) { return b[prop] == null ? a : a + b[prop]; }, 0); }; 
+120
javascript arrays angularjs prototype-programming
Apr 23 '14 at
source share
13 answers

Updated Answer

Due to all the drawbacks of adding a function to the Array prototype, I am updating this answer to provide an alternative that supports syntax similar to the syntax originally requested in the question.

 class TravellerCollection extends Array { sum(key) { return this.reduce((a, b) => a + (b[key] || 0), 0); } } const traveler = new TravellerCollection(...[ { description: 'Senior', Amount: 50}, { description: 'Senior', Amount: 50}, { description: 'Adult', Amount: 75}, { description: 'Child', Amount: 35}, { description: 'Infant', Amount: 25 }, ]); console.log(traveler.sum('Amount')); //~> 235 

Original answer

Since this is an array, you can add a function to the Array prototype.

 traveler = [ { description: 'Senior', Amount: 50}, { description: 'Senior', Amount: 50}, { description: 'Adult', Amount: 75}, { description: 'Child', Amount: 35}, { description: 'Infant', Amount: 25 }, ]; Array.prototype.sum = function (prop) { var total = 0 for ( var i = 0, _len = this.length; i < _len; i++ ) { total += this[i][prop] } return total } console.log(traveler.sum("Amount")) 

Violin: http://jsfiddle.net/9BAmj/

+76
Apr 23 '14 at
source share

I know that this question has an accepted answer, but I thought that I would use an alternative that uses array.reduce , seeing that summing an array is a canonical example for shorthand:

 $scope.sum = function(items, prop){ return items.reduce( function(a, b){ return a + b[prop]; }, 0); }; $scope.travelerTotal = $scope.sum($scope.traveler, 'Amount'); 

Fiddle

+196
Apr 23 '14 at 15:58
source share

Another example: the native JavaScript Map and Reduce functions were created for this (Map and Reduce are powerful languages โ€‹โ€‹in many languages).

 var traveler = [{description: 'Senior', Amount: 50}, {description: 'Senior', Amount: 50}, {description: 'Adult', Amount: 75}, {description: 'Child', Amount: 35}, {description: 'Infant', Amount: 25}]; function amount(item){ return item.Amount; } function sum(prev, next){ return prev + next; } traveler.map(amount).reduce(sum); // => 235; // or use arrow functions traveler.map(item => item.Amount).reduce((prev, next) => prev + next); 

Note : creating separate smaller functions, we get the opportunity to use them again.

 // Example of reuse. // Get only Amounts greater than 0; // Also, while using Javascript, stick with camelCase. // If you do decide to go against the standards, // then maintain your decision with all keys as in... // { description: 'Senior', Amount: 50 } // would be // { Description: 'Senior', Amount: 50 }; var travelers = [{description: 'Senior', amount: 50}, {description: 'Senior', amount: 50}, {description: 'Adult', amount: 75}, {description: 'Child', amount: 35}, {description: 'Infant', amount: 0 }]; // Directly above Travelers array I changed "Amount" to "amount" to match standards. function amount(item){ return item.amount; } travelers.filter(amount); // => [{description: 'Senior', amount: 50}, // {description: 'Senior', amount: 50}, // {description: 'Adult', amount: 75}, // {description: 'Child', amount: 35}]; // Does not include "Infant" as 0 is falsey. 
+89
Apr 07 '17 at 15:24
source share

I always avoid changing the prototype method and adding a library, so this is my solution:

Just use the Reduce Array prototype method.

 // + operator for casting to Number items.reduce((a, b) => +a + +b.price, 0); 
+67
Mar 03 '18 at 21:57
source share

I thought I would throw two cents on this: this is one of those operations that should always be purely functional, and not rely on any external variables. Some have already given a good answer, using reduce is the way to go.

Since most of us can already afford to use ES2015 syntax, here's my suggestion:

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

We make it an immutable function while we are on it. What reduce does here is simple: Start with a value of 0 for the battery and add the value of the current element with a loop to it.

Yay for functional programming and ES2015! :)

+19
Jun 15 '16 at 20:47
source share

You can do the following:

 $scope.traveler.map(o=>o.Amount).reduce((a,c)=>a+c); 
+14
09 Oct '18 at 20:56
source share

An alternative to improve the readability and use of Map and Reduce :

 const traveler = [ { description: 'Senior', amount: 50 }, { description: 'Senior', amount: 50 }, { description: 'Adult', amount: 75 }, { description: 'Child', amount: 35 }, { description: 'Infant', amount: 25 }, ]; const sum = traveler .map(item => item.amount) .reduce((prev, curr) => prev + curr, 0); 

Reusable Function:

 const calculateSum = (obj, field) => obj .map(items => items.attributes[field]) .reduce((prev, curr) => prev + curr, 0); 
+11
Apr 16 '19 at 11:09 on
source share

I am not sure if this has been mentioned yet. But there is a lodash function for this. The snippet below, where the value is your attribute, and the sum is the "value".

 _.sumBy(objects, 'value'); _.sumBy(objects, function(o) { return o.value; }); 

Both will work.

+4
Feb 19 '18 at 13:59
source share

you can also use Array.prototype.forEach ()

 let totalAmount = 0; $scope.traveler.forEach( data => totalAmount = totalAmount + data.Amount); return totalAmount; 
+1
Jun 14 '18 at 7:24
source share

Here is a single line using ES6 arrow functions.

 const sumPropertyValue = (items, prop) => items.reduce((a, b) => a + b[prop], 0); // usage: const cart_items = [ {quantity: 3}, {quantity: 4}, {quantity: 2} ]; const cart_total = sumPropertyValue(cart_items, 'quantity'); 
+1
Apr 6 '19 at 3:27
source share

How to sum an array of objects using javascript

 const traveler = [ { description: 'Senior', Amount: 50}, { description: 'Senior', Amount: 50}, { description: 'Adult', Amount: 75}, { description: 'Child', Amount: 35}, { description: 'Infant', Amount: 25 } ]; 

 const traveler = [ { description: 'Senior', Amount: 50}, { description: 'Senior', Amount: 50}, { description: 'Adult', Amount: 75}, { description: 'Child', Amount: 35}, { description: 'Infant', Amount: 25 }, ]; function sum(arrayData, key){ return arrayData.reduce((a,b) => { return {Amount : a.Amount + b.Amount} }) } console.log(sum(traveler)) 
''
+1
Apr 12 '19 at 7:59
source share

I have already used jquery. But I think this is intuitive enough to just have:

 var total_amount = 0; $.each(traveler, function( i, v ) { total_amount += v.Amount ; }); 

Essentially, this is just a short version of @akhouri's answer.

0
Aug 28 '18 at 12:17
source share

Here is a solution that I consider more flexible:

 function sumOfArrayWithParameter (array, parameter) { let sum = null; if (array && array.length > 0 && typeof parameter === 'string') { sum = 0; for (let e of array) if (e && e.hasOwnProperty(parameter)) sum += e[parameter]; } return sum; } 

To get the amount, simply use it as follows:

 let sum = sumOfArrayWithParameter(someArray, 'someProperty'); 
0
Aug 10 '19 at 13:45
source share



All Articles