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 have a total Amount of this array I'm 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;
}
It's easy when is only one array, but I have others arrays with a different property name that I would like to sum.
I would be happier If I could do something like this:
$scope.traveler.Sum({ Amount });
But I don't know how to go through this in a way that I could reuse it in the future like this:
$scope.someArray.Sum({ someProperty });
This question is related to
javascript
arrays
prototype-programming
Alternative for improved readability and using 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);
Re-useable function:
const calculateSum = (obj, field) => obj
.map(items => items.attributes[field])
.reduce((prev, curr) => prev + curr, 0);
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');
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);
How to sum array of object 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 = [_x000D_
{ description: 'Senior', Amount: 50},_x000D_
{ description: 'Senior', Amount: 50},_x000D_
{ description: 'Adult', Amount: 75},_x000D_
{ description: 'Child', Amount: 35},_x000D_
{ description: 'Infant', Amount: 25 },_x000D_
];_x000D_
function sum(arrayData, key){_x000D_
return arrayData.reduce((a,b) => {_x000D_
return {Amount : a.Amount + b.Amount}_x000D_
})_x000D_
}_x000D_
console.log(sum(traveler))
_x000D_
You can do the following:
$scope.traveler.map(o=>o.Amount).reduce((a,c)=>a+c);
Here is a one-liner 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');
I thought I'd drop my two cents on this: this is one of those operations that should always be purely functional, not relying on any external variables. A few already gave a good answer, using reduce
is the way to go here.
Since most of us can already afford to use ES2015 syntax, here's my proposition:
const sumValues = (obj) => Object.keys(obj).reduce((acc, value) => acc + obj[value], 0);
We're making it an immutable function while we're at it. What reduce
is doing here is simply this:
Start with a value of 0
for the accumulator, and add the value of the current looped item to it.
Yay for functional programming and ES2015! :)
I was already using jquery. But I think its intuitive enough to just have:
var total_amount = 0;
$.each(traveler, function( i, v ) { total_amount += v.Amount ; });
This is basically just a short-hand version of @akhouri's answer.
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.
Use reduce with destructuring to sum Amount:
const traveler = [
{ description: 'Senior', Amount: 50 },
{ description: 'Senior', Amount: 50 },
{ description: 'Adult', Amount: 75 },
{ description: 'Child', Amount: 35 },
{ description: 'Infant', Amount: 25 },
];
console.log(traveler.reduce((n, {Amount}) => n + Amount, 0))
Here's a solution I find 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 sum, simply use it like that:
let sum = sumOfArrayWithParameter(someArray, 'someProperty');
It's working for me in TypeScript
and JavaScript
:
let lst = [_x000D_
{ description:'Senior', price: 10},_x000D_
{ description:'Adult', price: 20},_x000D_
{ description:'Child', price: 30}_x000D_
];_x000D_
let sum = lst.map(o => o.price).reduce((a, c) => { return a + c });_x000D_
console.log(sum);
_x000D_
I hope is useful.
From array of objects
function getSum(array, column)
let values = array.map((item) => parseInt(item[column]) || 0)
return values.reduce((a, b) => a + b)
}
foo = [
{ a: 1, b: "" },
{ a: null, b: 2 },
{ a: 1, b: 2 },
{ a: 1, b: 2 },
]
getSum(foo, a) == 3
getSum(foo, b) == 6
I'm not sure this has been mentioned yet. But there is a lodash function for that. Snippet below where value is your attribute to sum is 'value'.
_.sumBy(objects, 'value');
_.sumBy(objects, function(o) { return o.value; });
Both will work.
can also use Array.prototype.forEach()
let totalAmount = 0;
$scope.traveler.forEach( data => totalAmount = totalAmount + data.Amount);
return totalAmount;
Source: Stackoverflow.com