I have an array of objects that looks like this:
var data = [{costOfAirtickets: 2500, costOfHotel: 1200},{costOfAirtickets: 1500, costOfHotel: 1000}]
and I want to sum each element in the array to produce an array like this:
var result = [{costOfAirtickets: 4000, costOfHotel: 2200}]
I have used a map and reduce function but I was able to only sum an individual element like so:
data.map(item => ite.costOfAirtickets).reduce((prev, next)=>prev + next); // 22
At the moment this produces a single value which is not what I want as per initial explanation.
Is there a way to do this in Javascript or probably with lodash.
Here is a
lodash
approachIt will sum by all the unique keys.
Wrap your result to a
[...]
or use a.castArray()
at the end before unwrapping using.value()
in case you want a array as result.You don't need to map the array, you're really just reducing things inside it.
In one go, you could do something like
Lodash
Using
lodash
reduce and _.mergeWith this is a one liner:ES6 Only
If you do NOT want to mutate the original array you can utilize ES6 reduce, Object.entries, and forEach like this:
If we do not care about mutating the initial
data
array then we can have a one liner solution:More readable:
The only difference between the mutating and not mutating examples is the initial value for the
reduce
(and also the fact that with the mutating we use the 0 index to as an accumulator for the sums). In the mutating ones there is noinitial value
where in the others we start with empty object literal.if you need the result to be an array specifically then return
[data]
for the mutating examples and[result]
for the pure examples.Another solution would be to use
Map
(not Array.prototype.map) as it has several notable differences compared to objects:Explanation
Outer loop
The above first iterates over your
data
array using thereduce
method. Each object within that I'll be referring to as a record -- distinguished in the code via the variable,rcd
.Each iteration of reduce returns a value which is passed as the first argument to the next iteration of the loop. In this case, the parameter
collection
holds that argument, which is your set of sums.Inner loop
Within the
reduce
loop, each key/value pair of the record is iterated over usingforEach
. To get the key/value pair theObject.entries
method is used. Using array destructuring these arguments can be directly assigned to the respective variables,key
andvalue
Retrieving/Setting values
Unlike a primitive object,
Map
has its own methods for getting and setting its entries usingget()
andset()
. So first retrieve the previous sum usingget()
, if it's not set then default to0
, which is what the|| 0
does. At that point, you can assume the previous sum is at least 0 or greater and add the current key's value onto it.Alternatives to Map
If you find Map is a bit heavy-handed, you may also use a similar object such as Set, which has many of the same methods (except the
get()
), or you could also use a primitive object (i.e.{}
).This is the easiest approach I could think off
Use Lodash to simplify your life.
Explanation:
_.sum(_.map(data, key))
: generates sum of each array_.zipObject
: zips the results with the array sumkeys.map()
for sum of each key as_.map
does not guarantee order.Documentation: