Reputation: 505
Suppose to have an array of two or more objects as:
const arr =[{PM1:10, PM10:20},{PM1:20, PM10:30, CO:27}, {NO2:30}]
How can I efficiently compute average values for each property in the objects comprising the array? I don't know in advance the properties in each object and even if there are common properties. I would expect a result:
{PM1:15, PM10:25, CO:27, NO2:30}
I suppose that I can use reduce but I can't figure it out how.
Upvotes: 0
Views: 161
Reputation: 1074495
You can loop through the property names of an object using either for-in
(which includes inherited properties) or an array from Object.keys
(which doesn't). In both cases, only enumerable properties are included.
For instance:
const arr =[{PM1:10, PM10:20},{PM1:20, PM10:30, CO:27}, {NO2:30}];
const result = {};
const counts = new Map();
for (const element of arr) {
for (const key in element) {
if (Object.hasOwn(element, key)) {
// Count this property
counts.set(key, (counts.get(key) ?? 0) + 1);
// Add it to the sum
result[key] = (result[key] ?? 0) + element[key];
}
}
}
// Update with the averages
for (const [key, count] of counts) {
result[key] = result[key] / counts.get(key);
}
Live Example:
// Quick-and-dirty polyfill for older environments without `Object.hasOwn`:
if (!Object.hasOwn) {
Object.defineProperty(Object, "hasOwn", {
value: Function.prototype.call.bind(Object.prototype.hasOwnProperty),
writable: true,
configurable: true,
});
}
const arr =[{PM1:10, PM10:20},{PM1:20, PM10:30, CO:27}, {NO2:30}];
const result = {};
const counts = new Map();
for (const element of arr) {
for (const key in element) {
if (Object.hasOwn(element, key)) {
// Count this property
counts.set(key, (counts.get(key) ?? 0) + 1);
// Add it to the sum
result[key] = (result[key] ?? 0) + element[key];
}
}
}
// Update with the averages
for (const [key, count] of counts) {
result[key] = result[key] / counts.get(key);
}
console.log(result);
Upvotes: 1
Reputation: 22320
just 2 reduce...
const arr =
[ { PM1:10, PM10:20}
, { PM1:20, PM10:30, CO:27}
, { NO2:30 }
]
const average =
arr.reduce((a,c)=>
{
for(let key in c)
{
let line = a.find( x=>x.k === key )
if (!line) a.push( line = { k:key, sum:0, nb:0 } )
line.sum += c[key]
++line.nb
}
return a
},
[]).reduce((a,c)=>
{
a[c.k] = c.sum / c.nb
return a
},{})
console.log ( average )
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 0