Better way to sum a property value in an array
Solution 1:
I know that this question has an accepted answer but I thought I'd chip in with an alternative which uses array.reduce, seeing that summing an array is the canonical example for reduce:
$scope.sum = function(items, prop){
return items.reduce( function(a, b){
return a + b[prop];
}, 0);
};
$scope.travelerTotal = $scope.sum($scope.traveler, 'Amount');
Fiddle
Solution 2:
Just another take, this is what
native
JavaScript functionsMap
andReduce
were built for (Map and Reduce are powerhouses 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: by making separate smaller functions we get the ability 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.
Solution 3:
Updated Answer
Due to all the downsides of adding a function to the Array prototype, I am updating this answer to provide an alternative that keeps the 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 it is an array you could 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"))
The Fiddle: http://jsfiddle.net/9BAmj/
Solution 4:
I always avoid changing prototype method and adding library so this is my solution:
Using reduce Array prototype method is sufficient
// + operator for casting to Number
items.reduce((a, b) => +a + +b.price, 0);