1. The task
Take this array of objects:
[{ x: 0, y: 0, z: 0 }, { x: 1, y: 1, z: 1 }, { x: 2, y: 2, z: 2 }, { x: 3, y: 3, z: 3 }, { x: 4, y: 4, z: 4 }]
Sum the values together and reduce the array to following:
{ x: 10, y: 10, z: 10 }
Additionally, we might want to calculate the average of all the values:
{ x: 2, y: 2, z: 2 }
2. Approaches
Depending on the data structure there are two different ways of approaching the problem
Data structure is known
Assuming we have data structure, where we know the keys:
interface sampleObject {
x: number
y: number
z: number
}
const sample: sampleObject[] = [{ x: 0, y: 0, z: 0 }, { x: 1, y: 1, z: 1 }, { x: 2, y: 2, z: 2 }, { x: 3, y: 3, z: 3 }, { x: 4, y: 4, z: 4 }]
const result: sampleObject
(expressed in TypeScript)
Solution
const result = sample.reduce((previous, current, index, array) => {
return {
x: previous.x + current.x,
y: previous.y + current.y,
z: previous.z + current.z
}
})
Output
{ x: 10, y: 10, z: 10 }
Explanation
Call the .reduce function, on the sample Array
sample.reduce((previous, current, index, array) => {
Return an Object, in which previous x, y, z values were added to current x, y, z values
return {
x: previous.x + current.x,
y: previous.y + current.y,
z: previous.z + current.z
}
})
Data structure is unknown
Assuming we have data structure in which the Object structure is unknown or are in a use-case, where expressing the structure is not necessary or inconvenient:
interface sampleObject {
[key: string]: number
}
const sample: sampleObject[] = [{ x: 0, y: 0, z: 0 }, { x: 1, y: 1, z: 1 }, { x: 2, y: 2, z: 2 }, { x: 3, y: 3, z: 3 }, { x: 4, y: 4, z: 4 }]
const result: sampleObject
(expressed in TypeScript)
Traditional way
const result = {}
sample.forEach((entry) => {
for (let key in entry) {
if (!result[key]) result[key] = entry[key]
else result[key] += entry[key]
}
})
Output
{ x: 10, y: 10, z: 10 }
Explanation
Create an empty Object, called result:
const result = {}
Iterate each entry in the sample Array:
sample.forEach((entry) => {
Create a for loop to iterate each key in entry Object:
for (let key in entry) {
If the key is not in the result Object, add it and the entry’s value into the result Object:
if (!result[key]) result[key] = entry[key]
If the key is in the result Object, add its value to current entry value:
else result[key] += entry[key]
}
})
Preferred way
const result = sample.reduce((previous, current, index, array) => {
Object.keys(current).forEach(key => {
current[key] += previous[key]
})
return current
})
Output
{ x: 10, y: 10, z: 10 }
Explanation
Call the .reduce function, on the sample Array
sample.reduce((previous, current, index, array) => {
Iterate over current Object keys using Object.keys
Object.keys(current).forEach(key => {
Add current key value to previous key value
current[key] += previous[key]
})
Return current Object
return current
})
4. Calculating the average
Modify previous examples to calculate the average
When data structure is known
const result = sample.reduce((previous, current, index, array) => {
let x = previous.x + current.x
let y = previous.y + current.y
let z = previous.z + current.z
if (index === array.length - 1) {
x /= array.length
y /= array.length
z /= array.length
}
return {x, y, z}
})
Output
{ x: 2, y: 2, z: 2 }
Explanation
const result = sample.reduce((previous, current, index, array) => {
- return {
- x: previous.x + current.x,
- y: previous.y + current.y,
- z: previous.z + current.z
+ let x = previous.x + current.x
+ let y = previous.y + current.y
+ let z = previous.z + current.z
+
+ if (index === array.length - 1) {
+ x /= array.length
+ y /= array.length
+ z /= array.length
}
+
+ return {x, y, z}
})
(shown as diff)
If current element is the last in the array, divide x, y, z by array length
When data structure is unknown
const result = sample.reduce((previous, current, index, array) => {
Object.keys(current).forEach(key => {
current[key] += previous[key]
if (index === array.length - 1) current[key] /= array.length
})
return current
})
Output
{ x: 2, y: 2, z: 2 }
Explanation
const result = sample.reduce((previous, current, index, array) => {
Object.keys(current).forEach(key => {
current[key] += previous[key]
+ if (index === array.length - 1) current[key] /= array.length
})
return current
})
(shown as diff)
If current element is the last in the array, divide the current key by array length
5. Bonus: calculate multiple arrays
If you want to calculate on multiple arrays, you can concatenate them using the spread operator
const sample = [...sample_a, ...sample_b]
Now you should be able to understand how to calculate the sum of array of objects and how to calculate the average of array of objects in JavaScript