理解 JavaScript 中的 map()、filter() 和 reduce()
目录
介绍
在上一篇文章中,我们讨论了“一等函数”以及 JavaScript 如何将函数视为一等公民。
Higher Orders Functions
函数式是指接受一个或多个函数作为参数,并且/或者返回一个函数的函数。这个概念源于函数式编程。JavaScript 是一种大量使用函数式编程概念的语言,Higher-Order Functions
也是其中之一。
在这篇文章中,我们将讨论map()
,filter()
以及reduce()
一些最著名和最易于使用的高阶函数。
什么是地图?
该方法通过对调用数组中的每个元素调用提供的函数
map()
来创建一个新数组。
假设我们要创建一个包含数字数组的双精度值的新数组。
一种方法是创建函数 double 并对 forEach 中的每个元素调用它。
使用 forEach 编写的 Map
const numbers = [1, 2, 3];
const result = [];
const double = (number) => {
return number * 2;
};
// Iterate over an array
numbers.forEach((number) => {
result.push(double(number));
})
// [2 4 6]
console.log(result);
这就是map
发挥作用的地方!我们不需要手动调用函数,而是可以将函数传递给 map,JavaScript 会在每个元素上为我们调用该函数!
不使用 forEach 编写的 Map
const numbers = [1, 2, 3];
const double = (number) => {
return number * 2;
};
const result = numbers.map(double);
//[2,4,6]
console.log(result);
现在让我们看一些可以使用 map 的其他示例
在下面的例子中,我们使用 map 创建一个包含每个人全名的新数组。
const people = [{
first_name: "Michael",
last_name: "Jordan"
}, {
first_name: "LeBron",
last_name: "James"
}, {
first_name: "Stephen",
last_name: "Curry"
}];
const fullNames = people.map((person) => {
return `${person.first_name} ${person.last_name}`;
});
// [ 'Michael Jordan', 'LeBron James', 'Stephen Curry' ]
console.log(fullNames);
在下面的例子中,我们创建了一个包含每天前两个字母的新数组。
const days = [
'Sunday',
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday'
];
const newDays = days.map((day) => {
return day.substring(0,2);
});
// [ 'Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa' ]
console.log(newDays);
什么时候应该使用地图?
- 当你想要创建一个与原始数组长度相同的新数组时。
- 当你想将一个事物的数组转换为另一个事物的数组时。
什么是过滤器?
该
filter()
方法创建一个新数组,其中包含通过所提供函数实现的测试的所有元素。
- 调用
filter()
将返回一个新数组。- 使用的回调函数
filter
应该返回true
或false
。
true
当前元素是否应该出现在新数组中。false
如果当前元素不应该出现在新数组中。
假设我们要创建一个包含数字数组的偶数的新数组。
一种方法是创建函数 isEven 来检查数字是否为偶数,并对 forEach 中的每个元素调用它。
使用 forEach 编写的过滤器
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const evenNumbers = [];
const isEven = (number) => {
return number % 2 === 0;
};
// 2. Iterate over an array
numbers.forEach((number) => {
if (isEven(number)) {
evenNumbers.push(number);
}
});
// [ 2, 4, 6, 8, 10 ]
console.log(evenNumbers);
不使用 forEach 编写的过滤器
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const isEven = (number) => {
return number % 2 === 0;
};
const evenNumbers = numbers.filter(isEven);
// [ 2, 4, 6, 8, 10 ]
console.log(evenNumbers);
现在让我们看一些其他可以使用过滤器的例子
在下面的例子中,我们创建了一个新数组,其中包含名字不超过六个字符的人。
const people = [{
first_name: "Michael",
last_name: "Jordan"
}, {
first_name: "LeBron",
last_name: "James"
}, {
first_name: "Stephen",
last_name: "Curry"
}];
const short = people.filter((person) => {
return person.first_name.length <= 6;
});
// [ { first_name: 'LeBron', last_name: 'James' } ]
console.log(short);
在下面的例子中,我们有一个包含每周天数的数组,我们想要创建一个新数组,该数组仅包含字母数量小于 7 的天数。
const days = [
'Sunday',
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday'
];
// create a new array with only the days that the length of their characters is less than 7
const shortDays = days.filter(day => {
return day.length < 7;
});
// [ 'Sunday', 'Monday', 'Friday' ]
console.log(shortDays);
何时使用过滤器:
- 当您想要一个不同长度的新数组时,基于数组中只有某些元素满足的某些条件。
什么是 Reduce?
该
reduce()
方法将一个函数应用于累加器和数组中的每个元素(从左到右),以将其缩减为单个值。累加器可以是任何类型(整数、字符串、对象等),并且必须在调用 reduce() 时实例化或传递。
- 调用
reduce()
将返回单个值。 - 使用的回调函数
reduce
将传递累加器值和数组中的元素。- 累加器值是上次调用回调函数返回的值。
- 回调函数应该始终返回一个值以供下次回调使用。
- 该函数的第三个参数
reduce()
是累加器的起始值。
假设我们要计算数字数组的总和。
使用 forEach 编写的 Reduce
const numbers = [1,2,3,4,5,6];
let sum = 0;
// Iterate over the array
numbers.forEach((number) => {
sum += number;
});
// 21
console.log(sum);
不使用 forEach 编写的 Reduce
const numbers = [1,2,3,4,5,6];
// Iterate over the array
const sum = numbers.reduce((sum, number) => {
sum += number;
return sum; // Return the accumulator
}, 0); // Initialize accumulator variable
// 21
console.log(sum);
现在让我们看一些我们可以使用 reduce 的其他示例。
在下面的例子中,我们创建了一个新对象,其中包含股票名称作为键,以及股票频率作为值。
const stocks = ['TSLA', 'PLTR', 'TSLA', 'AAPL', 'PLTR', 'TSLA'];
const result = stocks.reduce((stockFreq, stock) => {
if(stockFreq.hasOwnProperty(stock)) {
stockFreq[stock]++;
} else {
stockFreq[stock] = 1;
}
return stockFreq;
}, {});
// { TSLA: 3, PLTR: 2, AAPL: 1 }
console.log(result);
在下面的例子中,我们创建了一个包含每天前两个字母的新字符串。
const days = [
'Sunday',
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday'
];
const newDay = days.reduce((buffer ,day) => {
buffer += day.substring(0,2);
return buffer;
}, "");
// SuMoTuWeThFrSa
console.log(newDay);