'Compute average of properties in objects array

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.



Solution 1:[1]

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);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1