In JavaScript, array reduce is a predefined method for lowering an array to a single value by passing a callback function for each array element. It accepts a process run on all the elements of the supplied array in the left-to-right order. The single value returned is saved in the accumulator.
As a result, array reduction JavaScript is a non-mutating technique. Rather than modifying the real value variable, it will store the computed value in the accumulator while leaving the original value variable alone.
The reduce() method calls a user-supplied “reducer” callback function on each array element, sending in the result of the previous element’s calculation. The reducer’s outcome across all array elements is a single value.
“return value of the previous calculation” is not available the first time the callback is executed. In its absence, an initial value may be utilized. On the contrary, the zeroth index array element is used as the starting point, and iteration begins with the following member (index 1 instead of index 0).
The most straightforward use of reduce() is to return the total of all the entries in an array:
const arrayVals = [4, 5, 6, 7]; const initialValue = 0; const sumWithInitial = arrayVals.reduce( (previousValue, currentValue) => previousValue + currentValue, initialValue ); console.log(sumWithInitial); // expected output:
The reducer iteratively travels through the array, adding the value of the current array to the result from the previous step— until there are no more elements to add. Note that the result from the initial step is the running sum of all the previous steps.
The syntax is as follows:
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
Parameters
A “reducer” function is invoked with the following parameters:
previousValue
The outcome of the preceding call to callbackFn. If initialValue is given, the value of array[0] is returned on the first call.
currentValue
The current element’s value. If an initialValue was supplied, the array[0] value is returned on the first call; otherwise, the array[1] is returned.
currentIndex
The array index position of currentValue. If initialValue was given on the first call, 0; else, 1.
arr
It refers to the array that is being traversed.
Total
It is required. The function’s initialValue, or previously returned value – is the accumulated result of the callback function’s last call.
Optional initialValue
A value is initialized when the callback is called for the first time. When initialValue is supplied, currentValue is also set to the first value in the array. If no value is provided for initialValue, previousValue is set to the first in the array, and currentValue is set to the second in the array.
The value returned
The outcome is running the “reducer” callback function through the entire array to completion.
Exceptions: TypeError
There are no elements in the array, and no initialValue is specified.
Description
Reduce() accepts two parameters: a callback function and an optional initial value.
If an initial value is specified, reduce() executes the “reducer” callback function on each array element in the order established. If no initial value is set, reduce() invokes the callback function on each element in the array following the first. reduce() returns the value returned by the callback function on the array’s final iteration.
When to Avoid Using Reduce()
Recursive functions like reduce() can be extremely powerful, but they can also be challenging to grasp, especially for inexperienced JavaScript developers. If other array techniques result in clearer code, developers must consider the readability tradeoff against the other advantages of using reduce().
When reduce() is the best option, documentation and semantic variable name can help to mitigate readability issues.
Cases on the periphery
If the array only has a single element regardless of position and no initialValue is supplied, or if the initialValue is provided, but the array is empty, the solo value is returned without executing callbackFn.
If initialValue is specified and the array is not empty, the reduce method will always call the callback function beginning at index 0. If no initialValue is specified, the reduce method will behave differently for arrays with lengths greater than one, equal to one, and zero, as seen in the following example:
const findMaxValue = (aVal, bVal) => Math.max(aVal, bVal); // invoking the callback for each element in the provided array starting at index 0 [1, 100].reduce(findMaxValue, 50); // 100 [ 50].reduce(findMaxValue, 10); // 50 // callback is invoked once for the element at index 1 [1, 100].reduce(findMaxValue); // 100 // callback is not invoked [ 50].reduce(findMaxValue); // 50 [ ].reduce(findMaxValue, 1); // 1 [ ].reduce(findMaxValue); // TypeError
Observed behavior during array mutations
The reduce() method does not alter the array it is applied to. The array can, however, be changed by code inside the callback function. These are the array of mutation possibilities and how reduce() operates in these scenarios:
If individual items are added to the array after reduce() starts iterating over it, the callback function does not loop through the newly added features.
If existing array members are altered, the values given to the callback function will be the values from the first time reduce() was used on the array. Reduce does not visit array members that are destroyed after the call to reduce() begins and before being iterated over.
How reduce() works in the absence of an initial value
The following code demonstrates what occurs when we execute reduce() with an array when there is no present initial value.
const arrValue = [25, 26, 27, 28, 29]; function reducer(prevValue, currValue, index) { const returns = prevValue + currValue; console.log(`prevValue: ${prevValue}, currValue: ${currValue}, index: ${index}, returns: ${returns}`); return returns; } array.reduce(reducer);
The callback would be called four times, with the provided parameters and return values in each call.
How reduce() functions with a starting value
Here, we use the same approach to decrease the same array, but with an initialValue of 10 as the second argument to reduce():
[25, 26, 27, 28, 29].reduce((prevValue, currValue) => prevValue + currValue, 10)
The total of the values in an object array
To sum the values in an array of objects, you must first provide an initialValue, which ensures that each item travels through your method.
const objValues = [{ x: 1 }, { x: 2 }, { x: 3 }]; const sumValue = objValues.reduce( (prevValue, currValue) => prevValue + currValue.x, 0, ); console.log(sumValue);
Example: Make an array of arrays flat
const flatValue = [[0, 1], [2, 3], [4, 5]].reduce( (prevValue, currValue) => prevValue.concat(currValue), [], ); // flatValue is [0, 1, 2, 3, 4, 5]
Example: Counting the number of instances of a value in an object
const studentNames = ['Green', 'Angelo', 'Tyson', 'Mike', 'Laird']; const namesCounted = studentNames.reduce((compNames, val) => { compNames [val] ??= 0; compNames [val]++; // do not forget to return the object, or the subsequent iteration will be undefined return compNames; }, {}); // namesCounted is:
Example: Subtracting Numbers in Array
const numbers = [2000, 250, 500, 220, 300]; // subtract all numbers from the first number // since 1st element is called an accumulator rather than currentValue // 2000 - 250 - 400 - 220 - 300 let diffVal = numbers.reduce( (accumulator, currentValue) => accumulator - currentValue ); console.log(diffVal); const expenses = [2000, 2200, 3200, 5200, 700]; const wages = 15000; // function that subtracts all array elements from a given number // 15000 - 2000 - 2200 - 3200 - 5200 - 700 let balValue = expenses.reduce( (accumulator, currentValue) => accumulator - currentValue, wages ); console.log(balValue);
This example demonstrates the distinction between passing an initialValue and not an initialValue.
Example: Organizing items based on a property
const students = [ { name: 'Green', age: 21 }, { name: 'Angelo', age: 20 }, { name: 'Moss', age: 20 }, ]; function groupBy(objectArray, property) { return objectArray.reduce((acc, obj) => { const key = obj[property]; acc[key] ??= []; acc[key].push(obj); return acc; }, {}); } const groupedStudents = groupBy(students, 'age') // groupedStudents is: // { // 20: [ // { name: 'Angelo', age: 20 }, // { name: 'Moss', age: 20 } // ], // 21: [{ name: 'Green', age: 21 }] // }
Example: Change .filter().map() to.reduce()
Array.filter() and Array.map() traverses the array twice, whereas Array.reduce() achieves the same result while traversing the array just once, making it more efficient. If you prefer for loops, you may use Array.forEach() to filter and map while traversing once.
const numbers = [-5, 6, 2, 0]; const doubledPositiveNumbers = numbers.reduce((previousValue, currentValue) => { if (currentValue > 0) { const doubled = currentValue * 2; previousValue.push(doubled); } return previousValue; }, []); console.log(doubledPositiveNumbers); // [12, 4]
Example: Using the spread syntax and initialValue, concatenate arrays in an array of objects.
// programming languages - an array of objects // where object field "programmingLanguages" is a list of individual favorite programming languages const programmingLanguages = [ { name: 'Thomas', languages: ['Python', 'Django'], age: 41, }, { name: 'James', languages: ['JavaScript', 'AngularJS and React'], age: 25, }, { name: 'Given,' languages: [' Kotlin for Android', 'Java', 'JavaScript'], age: 23, }, ]; // allLanguages - a list that will contain all colleagues' programming languages // additional list contained in initialValue const allLanguages = programmingLanguages.reduce( (prevValue, currValue) => [...prevValue, ...currValue.languages], ['Alphabet'], );
Conclusion
In JavaScript, the arr.reduce() method reduces an array to a single value by executing a supplied function for each array value from left to right. The function’s return value is saved in an accumulator.