## 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