Modern JavaScript Web Development Cookbook
上QQ阅读APP看书,第一时间看更新

Reducing arrays to values

A simple question: how many times have you looped through an array to, say, add its numbers? The odds are, many times! This kind of operation —going through an array element by element performing some calculation to arrive at a final result—is the first one we will be implementing in a functional way, with .reduce().

The name .reduce() pretty much tells us what it does: it reduces a complete array to a single value. In other languages, this operation is called fold.

The most usual example, which most texts and articles show, is summing all of the elements of an array, and, since I'm traditionally minded, let's do just that! You must provide an initial value for your calculation (in this case, since we want a sum, it would be a zero) and a function that will update the calculated value when accessing each array element:

// Source file: src/map_filter_reduce.js

const someArray: Array<number> = [22, 9, 60, 12, 4, 56];

const totalSum = someArray.reduce(
(acc: number, val: number) => acc + val,
0
); // 163

How does it work? Internally, .reduce() starts by taking your initial value (zero, in this case) and then it calls the reducing function, giving it the accumulated total (acc) and the first element of the array (val). The function must update the accumulated total: in this case, it would calculate 0 + 22, so the next total would be 22. After, .reduce() would call the function again, passing it 22 (the updated total) and 9 (the second array element), and 31 would become the new accumulated total. This will proceed systematically through the complete array, until the final value (163) is computed. Note that all aspects of loop control are automatic, so there is no way you can err somewhere, and the code is quite declarative: you could almost read it as "reduce someArray to a value by summing all elements, starting with zero".

There are some more possibilities for .reduce(): check out  https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce for more information. You can also use .reduceRight(), which essentially works in the same fashion, but starting at the end of the array and proceeding backwards; see  https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/ReduceRight for more information.

Of course, you are not limited to processing arrays of numbers; you can deal with any data type, and the final result can also be any type. For example, you could use .reduce() to turn an array of names into an HTML bulleted list, as follows:

// Source file: src/map_filter_reduce.js

const names = ["Juan", "María", "Sylvia", "Federico"];

const bulletedList =
"<ul>" +
names.reduce((acc, val) => `${acc}<li>${val}</li>`, "") +
"</ul>";

// <ul><li>Juan</li><li>María</li><li>Sylvia</li><li>Federico</li></ul>

With a little practice, it's safe to say that you'll probably be able to transform any kind of calculation over an array into a .reduce() call with shorter, clearer code.