Reputation: 89
[
{
"id": 1,
"price": 100
},
{
"id": 1,
"price": 80
},
{
"id": 2,
"price": 8
},
{
"id": 1,
"price": 85
}
]
[
{
"id": 1,
"price": 88.33 // AVERAGE VALUE BETWEEN DUPLICATED OBJECTS
},
{
"id": 2,
"price": 8
}
]
I am merging and getting the average price for duplicated objects.
I have tried to use filter()
function but I removed the duplicated without merging the prices.
Upvotes: 0
Views: 60
Reputation: 11001
Use forEach
loop and build an object with keys as id
and aggregate price.
Use Object.values
of above object and calculate the averages.
const data = [
{
id: 1,
price: 100,
},
{
id: 1,
price: 80,
},
{
id: 2,
price: 8,
},
{
id: 1,
price: 85,
},
];
const process = (arr) => {
const res = {};
arr.forEach(({ id, price }) => {
res[id] ??= { id, sum: 0, count: 0 };
res[id].sum += price;
res[id].count += 1;
});
return Object.values(res).map(({ id, sum, count }) => ({
id,
price: sum / count,
}));
};
console.log(process(data));
Upvotes: 0
Reputation: 33726
If you want to avoid extra loops and extra properties is not a problem, you can use a getter for each object as follow:
You can use the function Array.prototype.reduce
for grouping objects by id
and the function Object.values
for extracting the grouped values.
The getter price
calculates the average when this property is accessed.
Extra properties:
{
count: Integer // count of repeated ids.
sum: Double // total sum of prices
}
const arr = [ { "id": 1, "price": 100 }, { "id": 1, "price": 80 }, { "id": 2, "price": 8 }, { "id": 1, "price": 85 } ],
result = Object.values(arr.reduce((r, {id, price}) => {
let current = (r[id] || (r[id] = {id, sum: 0, count: 0, get price() {
return this.sum / this.count;
}}));
current.sum += price;
current.count++;
return r;
}, {}));
console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 1
Reputation: 50639
You can use .reduce()
with an ES6 Map. By using reduce()
you can accumulate all objects into a Map, where the key is the id
from the object and the value is an accumulated array of price
values for the given id
. You can then convert the Map
back into an array using Array.from()
, where you can provide a mapping function to convert the [key, value]
pairs from the map into an object. The object's price
key will be the sum of all numbers in the value
array (arr
) divided by the length of the array, which will give you the average.
See example below:
const arr = [ { "id": 1, "price": 100 }, { "id": 1, "price": 80 }, { "id": 2, "price": 8 }, { "id": 1, "price": 85 } ];
const res = Array.from(arr.reduce((m, {id, price}) => {
return m.set(id, [...(m.get(id) || []), price]);
}, new Map), ([id, arr]) => ({id, price: arr.reduce((t, n) => t+n, 0) / arr.length}));
console.log(res);
Upvotes: 1