Array.prototype.reduce has not been used much in the past. I asked this question in the byteDance interview, and then I went to see MDN to understand it a little bit
usage
The reduce method passes each element of the array from left to right in turn to the callback function
are some of the common places
Counts the number of occurrences of each character in a string
Method 1 (this is the most common method I use without array.prototype.reduce):
const str = '9kFZTQLbUWOjurz9IKRdeg28rYxULHWDUrIHxCY6tnHleoJ'
const obj = {}
str.split(' ').forEach(item= > {
obj[item] ? obj[item]++ : obj[item] = 1
})
Copy the code
Method 2 (this is a little fun ):
const str = '9kFZTQLbUWOjurz9IKRdeg28rYxULHWDUrIHxCY6tnHleoJ'
const obj = {}
Array.from(str).reduce((accumulator, current) = > {
current in accumulator ? accumulator[current]++ : accumulator[current] = 1
return accumulator
}, obj)
Copy the code
Well, method 2 although the steps are more complicated than method 1 (actually not complicated roar), but is it more fun ?
Filters data in an array that meets multiple criteria at once
Method 1 (Common):
const arr = [
{
"name": "a1111"."age": 25
},
{
"name": "a1"."age": 26
},
{
"name": "a11"."age": 27
},
{
"name": "a"."age": 29
},
{
"name": "a11"."age": 29
},
{
"name": "a11"."age": 26
},
{
"name": "a111"."age": 25
},
{
"name": "a11"."age": 26
},
{
"name": "a1"."age": 26
},
{
"name": "a"."age": 26
}
]
arr.filter(item= > item.name.length === 3)
.filter(item= > item.age > 26)
/* [ { "name": "a11", "age": 27 }, { "name": "a11", "age": 29 } ] */
Copy the code
Method 2 Reduce method (thanks for @Zhanggenming’s proof, modified):
const arr = [
{
"name": "a1111"."age": 25
},
{
"name": "a1"."age": 26
},
{
"name": "a11"."age": 27
},
{
"name": "a"."age": 29
},
{
"name": "a11"."age": 29
},
{
"name": "a11"."age": 26
},
{
"name": "a111"."age": 25
},
{
"name": "a11"."age": 26
},
{
"name": "a1"."age": 26
},
{
"name": "a"."age": 26}]const filter1 = (arr) = > arr.filter(item= > item.name.length === 3)
const filter2 = (arr) = > arr.filter(item= > item.age > 26)
const fnArr = [filter1, filter2]
fnArr.reduce((accumulator, fn) = > {
accumulator = fn(accumulator)
return accumulator
}, arr)
/* [ { "name": "a11", "age": 27 }, { "name": "a11", "age": 29 } ] */
Copy the code
With this approach, let’s try implementing array.prortotype.reduce with a for loop
Let’s look at the parameters that Reduce receives:
arr.reduce(callback[, initialValue])
Copy the code
The reduce method takes a callback function as its first argument, along with an optional initialValue. The callback function also takes up to four arguments
- The return value of an accumulator callback; It is the cumulative value returned when the callback was last called. If initialValue is provided, its default value is initialValue, otherwise it is the first value of the array
- CurrentValue Specifies the element currently participating in the calculation
- CurrentIndex Array index of the current evaluated element
- Array Array of the current operation
With this in mind, implementing the Reduce approach is straightforward
Array.prototype.selfReduce = function() {
const ary = this
const { length } = ary
if (arguments.length === 0) {
throw new TypeError('undefined is not a function')}if (typeof arguments[0]! = ='function') {
throw new TypeError(arguments[0] + 'is not a function')}if (ary.length === 0 && arguments.length === 1) {
throw new TypeError('Reduce of empty array with no initial value')}const callback = arguments[0]
const startIndex = arguments.length >= 2 ? 0 : 1
let value = startIndex === 0 ? arguments[1] : ary[0]
for (let i = startIndex; i < length; i++) {
value = callback(value, ary[i], i, ary)
}
return value
}
Copy the code
At the same time,reduce also has its brother reduceRight, which, as its name suggests, passes each element of an array from right to left into a callback function. That realization reduceRight realization is also simple.
Array.prototype.selfReduceRight = function () {
const ary = this
const { length } = ary
if (arguments.length === 0) {
throw new TypeError('undefined is not a function')}if (typeof arguments[0]! = ='function') {
throw new TypeError(arguments[0] + 'is not a function')}if (ary.length === 0 && arguments.length === 1) {
throw new TypeError('Reduce of empty array with no initial value')}const startIndex = arguments.length >= 2 ? length - 1 : length - 2
const callback = arguments[0]
let value = startIndex === 0 ? arguments[1] : ary[length - 1]
for (let i = startIndex; i >= 0; i--) {
value = callback(value, ary[i], i, ary)
}
return value
}
Copy the code
Write in the last
A little bit of functional programming (FP)
- Compose (combination)
- Pipe (pipe)
compose
Compose executes from right to left
Here is the implementation of compose (unhandled exceptions)
const compose = function(. fns) {
return (val) = > {
return fns.reduceRight((acc, fn) = > {
return fn(acc);
}, val)
}
};
const add1 = x= > x + 1;
const mult2 = y= > y * 2;
const composeFn = compose(add1, mult2);
composeFn(5); // 11 = 5 * 2 + 1
Copy the code
pipe
Like the inside of the Unix “|”, execution of the pipe from left to right. The following is a very simple command to view the nginx process (written a little bit ).
ps -ef | grep nginx
Copy the code
Here is the implementation of PIPE (unhandled exception case)
const pipe = function(. fns) {
return (val) = > {
return fns.reduce((acc, fn) = > {
return fn(acc);
}, val)
}
};
const add1 = x= > x + 1;
const mult2 = y= > y * 2;
const pipeFn = pipe(add1, mult2);
pipeFn(5); // 12 = (5 + 1) * 2
Copy the code