Javascript Array.reduce() sounds awesome

Basic

Roughly speaking, it is a function that returns single value from multiple element (arrays and objects)

1
Array.prototype.reduce(callback( accumulator, currentValue[, index[, array]] )[, initialValue])
🀯 🀦 😱 😡 πŸ’€ πŸ’©β€¦

ℹ️ Basically, it seems to be better to set the initial value, because executing an empty array without an initial value may result in an error or unexpected execution result.
–> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce


πŸ™ Example 1: Calculate total

Let’s calculate total of array.

1
2
3
4
5
const arr = [1, 2, 3, 4, 5];

const total = arr.reduce((acc, cur) => acc + cur, 0);

console.log({ total }); // { total: 15 }
πŸ€” πŸ€” πŸ€”β€¦

OK… but make it a bit easier to read…

1
2
3
4
5
6
const arr = [1, 2, 3, 4, 5];

const callback = (acc, cur) => acc + cur;
const total = arr.reduce(callback, 0);

console.log({ total }); // { total: 15 }

πŸ€”β€¦ πŸ‘Œβ€¦


πŸ™ Example 2: Get a max number

1
2
3
const arr = [2, 1, 5, 3, 4];
const max = arr.reduce((a, b) => (a > b ? a : b), 0);
console.log({ max }); // {max: 5 }

πŸ™ Example 3: Remove value from array of element

e.g. Remove id and create a new array of elements with name key and types key

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const data = [
{ id: 1, name: 'Bulbasaur', types: ['grass', 'poison'] },
{ id: 4, name: 'Charmander', types: ['fire'] },
{ id: 6, name: 'Charizard', types: ['fire', 'flying'] },
];

const callback = (acc, cur) => {
const { name, types } = cur;
acc.push({ name, types });
return acc;
};

const result = data.reduce(callback, []);

console.log(result);

// [
// { name: 'Bulbasaur', types: [ 'grass', 'poison' ] },
// { name: 'Charmander', types: [ 'fire' ] },
// { name: 'Charizard', types: [ 'fire', 'flying' ] }
// ]

πŸ™ Example 4: Find Best/Worst Subject and calculate total score

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
const tests = [
{ subject: 'Math', score: 90 },
{ subject: 'Reading', score: 70 },
{ subject: 'Reading2', score: 83 },
{ subject: 'Science', score: 90 },
{ subject: 'Writing', score: 67 },
];

const initialValue = {
bestScore: 0,
bestSubject: [],
totalScore: 0,
worstScore: 0,
worstSubject: [],
};

const callback = (acc, curr) => {
acc.totalScore += curr.score;

if (!acc.bestSubject.length) {
// first roop should set the first items
acc.bestScore = curr.score;
acc.bestSubject.push(curr.subject);
acc.worstScore = curr.score;
acc.worstSubject.push(curr.subject);
} else {
// update Best Score and Best Subject
if (acc.bestScore < curr.score) {
acc.bestScore = curr.score;
acc.bestSubject = [];
acc.bestSubject.push(curr.subject);
} else if (acc.bestScore === curr.score) {
acc.bestScore = curr.score;
acc.bestSubject.push(curr.subject);
}

// update Worst Score and Worst Subject
if (acc.worstScore > curr.score) {
acc.worstScore = curr.score;
acc.worstSubject = [];
acc.worstSubject.push(curr.subject);
} else if (acc.worstScore === curr.score) {
acc.worstScore = curr.score;
acc.worstSubject.push(curr.subject);
}
}

return acc;
};

const result = tests.reduce(callback, initialValue);
const { bestScore, bestSubject, totalScore, worstScore, worstSubject } = result;

console.log(`
Best Subject: ${bestSubject.join(', ')} (Score: ${bestScore})
Worst Subject: ${worstSubject.join(', ')} (Score: ${worstScore})
Total Score: ${totalScore}`);

// Best Subject: Math, Science (Score: 90)
// Worst Subject: Writing (Score: 67)
// Total Score: 400

Well… it could be done better πŸ€”. I will update the logic later sometime.


πŸ™ Refs: