JavaScript数组常用的方法有哪些?map、filter、reduce 的区别和使用场景是什么?
JavaScript数组常用的方法有哪些?map、filter、reduce 的区别和使用场景是什么?
JavaScript 数组常用方法
JavaScript 数组有很多实用的方法,以下先简单介绍一些常见的基础方法,再重点讲解 map、filter、reduce 这三个高阶函数。
1. 基础常用方法
push() 和 pop()
push():就像往一个箱子里放东西,它会把一个或多个元素添加到数组的末尾,然后返回新数组的长度。pop():类似于从箱子里拿出最上面的东西,它会移除数组的最后一个元素,并返回这个被移除的元素。
let fruits = ['apple', 'banana'];
// 使用 push() 添加元素
let newLength = fruits.push('cherry');
console.log(newLength); // 输出: 3
console.log(fruits); // 输出: ['apple', 'banana', 'cherry']// 使用 pop() 移除元素
let removedFruit = fruits.pop();
console.log(removedFruit); // 输出: 'cherry'
console.log(fruits); // 输出: ['apple', 'banana']
unshift() 和 shift()
unshift():好比在箱子最前面插入东西,它会把一个或多个元素添加到数组的开头,然后返回新数组的长度。shift():如同从箱子最前面拿走东西,它会移除数组的第一个元素,并返回这个被移除的元素。
let numbers = [2, 3];
// 使用 unshift() 添加元素
let newLength2 = numbers.unshift(1);
console.log(newLength2); // 输出: 3
console.log(numbers); // 输出: [1, 2, 3]// 使用 shift() 移除元素
let removedNumber = numbers.shift();
console.log(removedNumber); // 输出: 1
console.log(numbers); // 输出: [2, 3]
splice()
splice() 就像一个“数组外科医生”,它可以删除、替换或插入元素。它接收三个参数,第一个是开始操作的索引,第二个是要删除的元素个数,后面还可以跟要插入的元素。
let colors = ['red', 'green', 'blue'];
// 删除元素
colors.splice(1, 1);
console.log(colors); // 输出: ['red', 'blue']// 插入元素
colors.splice(1, 0, 'yellow');
console.log(colors); // 输出: ['red', 'yellow', 'blue']// 替换元素
colors.splice(1, 1, 'orange');
console.log(colors); // 输出: ['red', 'orange', 'blue']
map、filter、reduce 的区别和使用场景
1. map()
- 区别:
map就像是一个“加工厂”,它会遍历数组中的每个元素,对每个元素执行你提供的函数,然后把处理后的结果组成一个新数组返回。新数组的长度和原数组一样,只是每个元素都经过了处理。 - 使用场景:当你需要对数组中的每个元素进行某种转换时,就可以使用
map。比如把数组中的每个数字都乘以 2。
let numbers = [1, 2, 3];
// 使用 map 将每个数字乘以 2
let newNumbers = numbers.map(function(num) {return num * 2;
});
console.log(newNumbers); // 输出: [2, 4, 6]
2. filter()
- 区别:
filter类似于一个“筛选器”,它会遍历数组中的每个元素,对每个元素执行你提供的函数,根据函数返回的布尔值来决定是否保留该元素。如果返回true,则该元素会被保留到新数组中;如果返回false,则该元素会被过滤掉。 - 使用场景:当你需要从数组中筛选出符合某种条件的元素时,就可以使用
filter。比如从数组中找出所有大于 5 的数字。
let numbers2 = [3, 6, 8, 2];
// 使用 filter 找出大于 5 的数字
let filteredNumbers = numbers2.filter(function(num) {return num > 5;
});
console.log(filteredNumbers); // 输出: [6, 8]
3. reduce()
- 区别:
reduce就像一个“累加器”或者“合并器”,它会遍历数组中的每个元素,对每个元素执行你提供的函数,并且会把上一次计算的结果传递给下一次计算。最后返回一个最终的结果。它接收两个参数,第一个是一个回调函数,第二个是初始值(可选)。 - 使用场景:当你需要对数组中的元素进行累加、合并等操作时,就可以使用
reduce。比如计算数组中所有数字的总和。
let numbers3 = [1, 2, 3, 4];
// 使用 reduce 计算数组元素的总和
let sum = numbers3.reduce(function(accumulator, currentValue) {return accumulator + currentValue;
}, 0);
console.log(sum); // 输出: 10
总结来说,map 用于元素转换,filter 用于元素筛选,reduce 用于元素合并或累加。
**在实际项目中,map、filter、reduce 方法通常如何搭配使用?
**
在实际项目中,map、filter 和 reduce 这三个数组方法经常搭配使用,以实现复杂的数据处理和转换。下面通过不同的实际场景示例,展示它们的搭配使用方式。
场景一:数据筛选与转换后求和
假设你有一个电商项目,需要计算所有已付款商品的总价。商品列表是一个包含多个商品对象的数组,每个商品对象有 price(价格)和 isPaid(是否付款)两个属性。
// 模拟商品列表
const products = [{ id: 1, price: 20, isPaid: true },{ id: 2, price: 30, isPaid: false },{ id: 3, price: 15, isPaid: true },{ id: 4, price: 40, isPaid: true }
];// 步骤 1:使用 filter 筛选出已付款的商品
const paidProducts = products.filter(product => product.isPaid);// 步骤 2:使用 map 提取已付款商品的价格
const paidPrices = paidProducts.map(product => product.price);// 步骤 3:使用 reduce 计算已付款商品的总价
const totalPrice = paidPrices.reduce((acc, price) => acc + price, 0);console.log(totalPrice); // 输出: 75
在这个例子中,首先使用 filter 方法筛选出已付款的商品,得到一个只包含已付款商品的新数组。然后使用 map 方法从这个新数组中提取出每个商品的价格,形成一个只包含价格的数组。最后使用 reduce 方法对这个价格数组进行累加,得到已付款商品的总价。
场景二:数据转换与筛选后统计数量
假设你在开发一个博客系统,需要统计所有发布状态为“已发布”且阅读量大于 100 的文章数量。文章列表是一个包含多个文章对象的数组,每个文章对象有 status(状态)和 views(阅读量)两个属性。
// 模拟文章列表
const articles = [{ title: '文章1', status: 'published', views: 120 },{ title: '文章2', status: 'draft', views: 80 },{ title: '文章3', status: 'published', views: 150 },{ title: '文章4', status: 'published', views: 50 }
];// 步骤 1:使用 map 转换文章对象为是否符合条件的布尔值
const isQualified = articles.map(article => article.status === 'published' && article.views > 100);// 步骤 2:使用 filter 筛选出符合条件的布尔值(即 true)
const qualifiedArticles = isQualified.filter(Boolean);// 步骤 3:使用 reduce 统计符合条件的文章数量
const count = qualifiedArticles.reduce((acc) => acc + 1, 0);console.log(count); // 输出: 2
这里先使用 map 方法将文章对象转换为布尔值,表示该文章是否符合“已发布且阅读量大于 100”的条件。接着使用 filter 方法筛选出布尔值为 true 的元素,得到一个只包含 true 的数组。最后使用 reduce 方法对这个数组进行累加,统计出符合条件的文章数量。
场景三:数据分组与统计
假设你在处理一个学生成绩数据,需要统计每个班级的总成绩。学生成绩数据是一个包含多个学生对象的数组,每个学生对象有 class(班级)和 score(成绩)两个属性。
// 模拟学生成绩数据
const students = [{ name: '张三', class: 'A', score: 80 },{ name: '李四', class: 'B', score: 90 },{ name: '王五', class: 'A', score: 70 },{ name: '赵六', class: 'B', score: 85 }
];// 使用 reduce 进行分组和统计
const classScores = students.reduce((acc, student) => {const { class: className, score } = student;if (!acc[className]) {acc[className] = 0;}acc[className] += score;return acc;
}, {});console.log(classScores); // 输出: { A: 150, B: 175 }
在这个例子中,主要使用 reduce 方法完成数据的分组和统计。reduce 的初始值是一个空对象 {},在回调函数中,根据学生的班级对成绩进行分组累加,最终得到每个班级的总成绩。如果需要对每个班级的总成绩进行进一步处理,比如转换为数组形式,可以结合 map 方法:
const classScoreArray = Object.entries(classScores).map(([className, totalScore]) => ({class: className,totalScore
}));console.log(classScoreArray);
// 输出: [ { class: 'A', totalScore: 150 }, { class: 'B', totalScore: 175 } ]
通过以上场景可以看出,map、filter 和 reduce 方法相互配合,能够高效地完成各种复杂的数据处理任务。在实际应用中,可以根据具体需求灵活组合使用这些方法。
在实际项目中,map、filter、reduce 方法的性能有何区别?
在实际项目中,map、filter 和 reduce 都是 JavaScript 数组的高阶函数,它们在性能方面存在一些区别,下面从时间复杂度、内存使用、实际应用场景等方面详细分析。
时间复杂度
map方法:map方法会遍历数组中的每个元素,对每个元素执行一次提供的回调函数,并将结果存储在一个新数组中。因此,map方法的时间复杂度是 O ( n ) O(n) O(n),其中 n n n 是数组的长度。因为它只需要对数组进行一次线性遍历。
const numbers = [1, 2, 3, 4, 5];
const squaredNumbers = numbers.map(num => num * num);
filter方法:filter方法同样会遍历数组中的每个元素,根据回调函数的返回值决定是否将该元素保留在新数组中。所以,filter方法的时间复杂度也是 O ( n ) O(n) O(n),需要对数组进行一次完整的遍历。
const numbers = [1, 2, 3, 4, 5];
const evenNumbers = numbers.filter(num => num % 2 === 0);
reduce方法:reduce方法会对数组中的每个元素执行一次回调函数,并将上一次回调的结果传递给下一次回调。其时间复杂度同样是 O ( n ) O(n) O(n),因为它也需要遍历数组一次。
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((acc, num) => acc + num, 0);
内存使用
map方法:map方法会创建一个与原数组长度相同的新数组,新数组中的每个元素是原数组对应元素经过处理后的结果。因此,它的内存使用主要取决于原数组的长度和处理后元素的大小。如果处理后的元素大小与原元素相近,那么内存使用会增加与原数组大小相近的空间。
const largeArray = new Array(1000000).fill(1);
const newArray = largeArray.map(num => num * 2);
filter方法:filter方法创建的新数组长度通常小于或等于原数组长度,具体取决于过滤条件。如果大部分元素都满足过滤条件,那么内存使用会接近原数组大小;如果只有少数元素满足条件,内存使用会相应减少。
const largeArray = new Array(1000000).fill(1);
const filteredArray = largeArray.filter(num => num % 2 === 0);
reduce方法:reduce方法不会创建新数组,而是返回一个单一的值或对象。因此,它的内存使用相对较小,主要取决于最终结果的大小。
const largeArray = new Array(1000000).fill(1);
const sum = largeArray.reduce((acc, num) => acc + num, 0);
实际应用场景对性能的影响
- 简单转换场景:如果只是对数组中的每个元素进行简单的转换,使用
map方法是最合适的。因为它的逻辑清晰,性能也比较稳定。例如,将数组中的每个数字转换为其平方值。
const numbers = [1, 2, 3, 4, 5];
const squaredNumbers = numbers.map(num => num * num);
- 筛选场景:当需要从数组中筛选出符合特定条件的元素时,使用
filter方法。它可以避免不必要的元素处理,提高性能。例如,从数组中筛选出所有偶数。
const numbers = [1, 2, 3, 4, 5];
const evenNumbers = numbers.filter(num => num % 2 === 0);
- 聚合场景:如果需要对数组元素进行聚合操作,如求和、求平均值等,使用
reduce方法。它可以在一次遍历中完成聚合,避免多次遍历数组。例如,计算数组中所有元素的总和。
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((acc, num) => acc + num, 0);
链式调用时的性能考虑
在实际项目中,经常会链式调用这三个方法。在链式调用时,每次调用都会创建一个新的中间数组(map 和 filter),这会增加内存使用和处理时间。可以考虑使用 reduce 方法来合并多个操作,减少中间数组的创建,提高性能。
// 链式调用 map 和 filter
const numbers = [1, 2, 3, 4, 5];
const result1 = numbers.map(num => num * 2).filter(num => num > 5);// 使用 reduce 合并操作
const result2 = numbers.reduce((acc, num) => {const doubled = num * 2;if (doubled > 5) {acc.push(doubled);}return acc;
}, []);
综上所述,map、filter 和 reduce 方法的时间复杂度相同,但在内存使用和适用场景上有所差异。在实际项目中,需要根据具体需求选择合适的方法,以提高代码的性能和效率。
除了 map、filter、reduce 之外,还有哪些常用的数组方法?
除了 map、filter、reduce 之外,JavaScript 数组还有许多其他常用的方法,下面为你详细介绍:
1. 元素添加与删除类
push() 和 pop()
push():用于在数组的末尾添加一个或多个元素,并返回新的数组长度。
const fruits = ['apple', 'banana'];
const newLength = fruits.push('cherry', 'date');
console.log(fruits); // 输出: ['apple', 'banana', 'cherry', 'date']
console.log(newLength); // 输出: 4
pop():用于移除数组的最后一个元素,并返回该元素。
const fruits = ['apple', 'banana', 'cherry'];
const removedFruit = fruits.pop();
console.log(fruits); // 输出: ['apple', 'banana']
console.log(removedFruit); // 输出: 'cherry'
unshift() 和 shift()
unshift():在数组的开头添加一个或多个元素,并返回新的数组长度。
const numbers = [2, 3];
const newLength = numbers.unshift(0, 1);
console.log(numbers); // 输出: [0, 1, 2, 3]
console.log(newLength); // 输出: 4
shift():移除数组的第一个元素,并返回该元素。
const numbers = [1, 2, 3];
const removedNumber = numbers.shift();
console.log(numbers); // 输出: [2, 3]
console.log(removedNumber); // 输出: 1
splice()
可以用于删除、插入或替换数组中的元素。它接收三个参数:起始索引、要删除的元素个数、要插入的元素(可选)。
const colors = ['red', 'green', 'blue'];
// 删除元素
colors.splice(1, 1);
console.log(colors); // 输出: ['red', 'blue']// 插入元素
colors.splice(1, 0, 'yellow');
console.log(colors); // 输出: ['red', 'yellow', 'blue']// 替换元素
colors.splice(1, 1, 'orange');
console.log(colors); // 输出: ['red', 'orange', 'blue']
2. 数组合并与截取类
concat()
用于合并两个或多个数组,并返回一个新数组,原数组不会被修改。
const arr1 = [1, 2];
const arr2 = [3, 4];
const arr3 = [5, 6];
const newArray = arr1.concat(arr2, arr3);
console.log(newArray); // 输出: [1, 2, 3, 4, 5, 6]
slice()
用于截取数组的一部分,并返回一个新数组,原数组不会被修改。它接收两个参数:起始索引和结束索引(可选,不包含该索引对应的元素)。
const numbers = [1, 2, 3, 4, 5];
const slicedArray = numbers.slice(1, 3);
console.log(slicedArray); // 输出: [2, 3]
3. 数组查找与排序类
indexOf() 和 lastIndexOf()
indexOf():返回指定元素在数组中第一次出现的索引,如果未找到则返回 -1。
const fruits = ['apple', 'banana', 'cherry', 'banana'];
const index = fruits.indexOf('banana');
console.log(index); // 输出: 1
lastIndexOf():返回指定元素在数组中最后一次出现的索引,如果未找到则返回 -1。
const fruits = ['apple', 'banana', 'cherry', 'banana'];
const lastIndex = fruits.lastIndexOf('banana');
console.log(lastIndex); // 输出: 3
find() 和 findIndex()
find():返回数组中满足提供的测试函数的第一个元素的值,如果没有找到则返回undefined。
const numbers = [1, 2, 3, 4, 5];
const foundNumber = numbers.find(num => num > 3);
console.log(foundNumber); // 输出: 4
findIndex():返回数组中满足提供的测试函数的第一个元素的索引,如果没有找到则返回 -1。
const numbers = [1, 2, 3, 4, 5];
const foundIndex = numbers.findIndex(num => num > 3);
console.log(foundIndex); // 输出: 3
sort()
用于对数组的元素进行排序,默认按照字符串的 Unicode 编码进行排序。可以传入一个比较函数来指定排序规则。
const numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5];
numbers.sort((a, b) => a - b);
console.log(numbers); // 输出: [1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9]
4. 数组转换与迭代类
join()
将数组的所有元素连接成一个字符串,并返回该字符串。可以指定连接符,默认为逗号。
const fruits = ['apple', 'banana', 'cherry'];
const fruitString = fruits.join(' - ');
console.log(fruitString); // 输出: 'apple - banana - cherry'
reverse()
用于颠倒数组中元素的顺序,原数组会被修改。
const numbers = [1, 2, 3, 4, 5];
numbers.reverse();
console.log(numbers); // 输出: [5, 4, 3, 2, 1]
forEach()
对数组的每个元素执行一次提供的函数,没有返回值。
const numbers = [1, 2, 3];
numbers.forEach(num => {console.log(num * 2);
});
// 输出: 2
// 输出: 4
// 输出: 6
concat() 方法与 push() 方法有什么区别?
concat() 和 push() 都是 JavaScript 数组中用于添加元素的方法,但它们在功能、使用方式、对原数组的影响以及返回值等方面存在明显区别,下面为你详细介绍:
1. 功能和使用方式
concat()方法:主要用于合并两个或多个数组,它可以接收数组或者单个值作为参数,将这些参数中的元素合并到一个新数组中。concat()方法不会修改原数组,而是返回一个新的合并后的数组。
const arr1 = [1, 2];
const arr2 = [3, 4];
const arr3 = 5;// 合并数组和单个值
const newArray = arr1.concat(arr2, arr3);
console.log(newArray); // 输出: [1, 2, 3, 4, 5]
console.log(arr1); // 输出: [1, 2],原数组未被修改
push()方法:用于在数组的末尾添加一个或多个元素。它直接修改调用该方法的原数组,并且返回新数组的长度。
const arr = [1, 2];
const newLength = arr.push(3, 4);
console.log(arr); // 输出: [1, 2, 3, 4],原数组被修改
console.log(newLength); // 输出: 4
2. 对原数组的影响
concat()方法:不改变原数组,它只是创建并返回一个新的数组,这个新数组包含了原数组和传入参数中的所有元素。原数组保持不变,这在需要保留原始数据的场景中非常有用。
const originalArray = [1, 2];
const anotherArray = [3, 4];
const combinedArray = originalArray.concat(anotherArray);
console.log(originalArray); // 输出: [1, 2]
push()方法:会直接修改调用它的数组,将新元素添加到原数组的末尾。这意味着原数组的内容会发生改变。
const originalArray = [1, 2];
originalArray.push(3);
console.log(originalArray); // 输出: [1, 2, 3]
3. 返回值
concat()方法:返回一个新的数组,这个新数组是原数组和传入参数合并后的结果。
const arr1 = [1, 2];
const arr2 = [3, 4];
const result = arr1.concat(arr2);
console.log(result); // 输出: [1, 2, 3, 4]
push()方法:返回添加元素后数组的新长度。
const arr = [1, 2];
const length = arr.push(3);
console.log(length); // 输出: 3
4. 处理多维数组的方式
concat()方法:对于传入的数组参数,它会将其元素展开并添加到新数组中,而不是将整个数组作为一个元素添加。
const arr1 = [1, 2];
const arr2 = [3, 4];
const result = arr1.concat(arr2);
console.log(result); // 输出: [1, 2, 3, 4]
push()方法:如果传入的是一个数组,它会将整个数组作为一个元素添加到原数组的末尾。
const arr = [1, 2];
const anotherArr = [3, 4];
arr.push(anotherArr);
console.log(arr); // 输出: [1, 2, [3, 4]]
综上所述,concat() 适用于需要合并数组且不改变原数组的场景,而 push() 适用于直接在原数组末尾添加元素并获取新数组长度的场景。
**slice() 和 splice() 方法有什么不同?
**
slice() 和 splice() 是 JavaScript 数组中用于处理数组元素的两个方法,它们在功能、使用方式、对原数组的影响等方面存在明显差异,以下是详细对比:
1. 功能用途
slice()方法:主要用于从原数组中提取一部分元素,创建并返回一个新数组,就像用刀从一块蛋糕上切下一部分,原蛋糕(原数组)不会被改变。常用于获取数组的子集,比如获取数组的前几个元素、中间一段元素等。splice()方法:功能更强大且灵活,它可以用于删除、插入或替换数组中的元素,相当于对原数组进行“手术”,会直接修改原数组。常用于需要对数组进行元素的增删改操作的场景。
2. 语法和参数
slice()方法:- 语法:
arr.slice([begin[, end]]) - 参数:
begin(可选):提取起始位置的索引,默认为 0。如果为负数,则从数组末尾开始计算。end(可选):提取结束位置的索引(不包含该索引对应的元素)。如果省略,则提取到数组末尾;如果为负数,则从数组末尾开始计算。
- 语法:
const fruits = ['apple', 'banana', 'cherry', 'date', 'elderberry'];
const slicedFruits = fruits.slice(1, 3);
console.log(slicedFruits); // 输出: ['banana', 'cherry']
console.log(fruits); // 输出: ['apple', 'banana', 'cherry', 'date', 'elderberry'],原数组未改变
splice()方法:- 语法:
arr.splice(start[, deleteCount[, item1[, item2[, ...]]]]) - 参数:
start:操作起始位置的索引。deleteCount(可选):要删除的元素个数。如果省略,则从start位置开始删除到数组末尾;如果为 0,则不删除元素。item1, item2, ...(可选):要插入到数组中的元素,从start位置开始插入。
- 语法:
const fruits = ['apple', 'banana', 'cherry', 'date', 'elderberry'];
// 删除元素
const removedFruits = fruits.splice(1, 2);
console.log(removedFruits); // 输出: ['banana', 'cherry']
console.log(fruits); // 输出: ['apple', 'date', 'elderberry'],原数组被修改// 插入元素
fruits.splice(1, 0, 'fig', 'grape');
console.log(fruits); // 输出: ['apple', 'fig', 'grape', 'date', 'elderberry']// 替换元素
fruits.splice(2, 1, 'honeydew');
console.log(fruits); // 输出: ['apple', 'fig', 'honeydew', 'date', 'elderberry']
3. 对原数组的影响
slice()方法:不会修改原数组,它只是从原数组中提取元素并返回一个新数组,原数组保持不变。这在需要保留原始数据,同时获取部分数据的场景中非常有用。splice()方法:会直接修改原数组,根据传入的参数进行元素的删除、插入或替换操作。原数组的内容会发生改变,适用于需要对数组进行实时修改的场景。
4. 返回值
slice()方法:返回一个新数组,包含从原数组中提取的元素。splice()方法:返回一个数组,包含从原数组中删除的元素。如果没有删除元素,则返回一个空数组。
综上所述,slice() 主要用于提取数组元素,不改变原数组;而 splice() 用于对数组进行增删改操作,会改变原数组。在实际使用中,应根据具体需求选择合适的方法。
在实际项目中,map、filter、reduce 如何选用方法?
在实际项目中,map、filter 和 reduce 是 JavaScript 数组非常实用的高阶函数,它们各自有独特的用途,选用时需要依据具体的业务需求,下面详细介绍选用这些方法的思路和实际场景示例。
1. map 方法
适用场景
当你需要对数组中的每个元素进行相同的转换操作,并且希望得到一个新数组,新数组的长度与原数组相同,只是元素的值经过了处理,这时就可以使用 map 方法。简单来说,就是“一个换一个”的操作。
示例
在一个电商项目中,有一个商品价格数组,需要将每个商品的价格增加 10%。
const prices = [100, 200, 300];
const newPrices = prices.map(price => price * 1.1);
console.log(newPrices);
// 输出: [110, 220, 330]
这里使用 map 方法对 prices 数组中的每个元素乘以 1.1,得到一个新的 newPrices 数组。
2. filter 方法
适用场景
当你需要从数组中筛选出符合特定条件的元素,形成一个新数组,新数组的长度可能小于原数组,这时就适合使用 filter 方法。可以把它想象成一个“筛子”,只让符合条件的元素通过。
示例
在一个学生成绩管理系统中,有一个学生成绩数组,需要筛选出成绩大于 80 分的学生。
const scores = [70, 85, 90, 60, 88];
const highScores = scores.filter(score => score > 80);
console.log(highScores);
// 输出: [85, 90, 88]
这里使用 filter 方法筛选出 scores 数组中大于 80 的元素,组成新的 highScores 数组。
3. reduce 方法
适用场景
reduce 方法适用于对数组元素进行聚合操作,将数组中的多个元素合并成一个单一的值或对象。常见的聚合操作包括求和、求平均值、统计数量、分组等。
示例
- 求和:计算一个数组中所有数字的总和。
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((acc, num) => acc + num, 0);
console.log(sum);
// 输出: 15
这里 reduce 方法从初始值 0 开始,依次将数组中的元素累加到 acc 中,最终得到总和。
- 分组:有一个学生信息数组,需要根据学生的班级进行分组。
const students = [{ name: '张三', class: 'A' },{ name: '李四', class: 'B' },{ name: '王五', class: 'A' }
];
const groupedStudents = students.reduce((acc, student) => {const className = student.class;if (!acc[className]) {acc[className] = [];}acc[className].push(student);return acc;
}, {});
console.log(groupedStudents);
// 输出: { A: [ { name: '张三', class: 'A' }, { name: '王五', class: 'A' } ], B: [ { name: '李四', class: 'B' } ] }
这里使用 reduce 方法将学生按班级分组,最终得到一个对象,对象的键是班级名,值是该班级的学生数组。
4. 组合使用
在实际项目中,还可能会组合使用这三个方法。例如,先使用 filter 筛选出符合条件的元素,再使用 map 对筛选后的元素进行转换,最后使用 reduce 进行聚合。
示例
有一个商品数组,需要筛选出价格大于 50 的商品,将这些商品的价格增加 10%,然后计算这些商品的总价。
const products = [{ name: '商品1', price: 30 },{ name: '商品2', price: 60 },{ name: '商品3', price: 80 }
];
const totalPrice = products.filter(product => product.price > 50).map(product => product.price * 1.1).reduce((acc, price) => acc + price, 0);
console.log(totalPrice);
// 输出: 154
这里先使用 filter 筛选出价格大于 50 的商品,再用 map 对筛选后的商品价格增加 10%,最后用 reduce 计算总价。
综上所述,选用 map、filter 还是 reduce 方法,关键在于明确业务需求是进行元素转换、筛选还是聚合,以及是否需要组合使用这些方法来完成更复杂的操作。
相关文章:
JavaScript数组常用的方法有哪些?map、filter、reduce 的区别和使用场景是什么?
JavaScript数组常用的方法有哪些?map、filter、reduce 的区别和使用场景是什么? JavaScript 数组常用方法 JavaScript 数组有很多实用的方法,以下先简单介绍一些常见的基础方法,再重点讲解 map、filter、reduce 这三个高阶函数。…...
vim修改只读文件
现象 解决方案 对于有root权限的用户,在命令行输入 :wq! 即可强制保存退出...
【DeepSeek】本地部署,保姆级教程
deepseek网站链接传送门:DeepSeek 在这里主要介绍DeepSeek的两种部署方法,一种是调用API,一种是本地部署。 一、API调用 1.进入网址Cherry Studio - 全能的AI助手选择立即下载 2.安装时位置建议放在其他盘,不要放c盘 3.进入软件后…...
为AI聊天工具添加一个知识系统 之114 详细设计之55 知识表征
本文要点 要点 项目名称:为使用AI聊天工具的聊天者添加一个知识系统 项目背景: 在现在各种AI聊天工具层出不穷的今天,我觉得特别需要一个通用的AI聊天工具的图形界面能够为每个聊天者(或一个利益相关者组织)建立自…...
centos 9 时间同步服务
在 CentOS 9 中,默认的时间同步服务是 chrony,而不是传统的 ntpd。 因此,建议使用 chrony 来配置和管理时间同步。 以下是使用 chrony 配置 NTP 服务的步骤: 1. 安装 chrony 首先,确保系统已安装 chrony。 在 CentOS…...
NCRE证书构成:全国计算机等级考试证书体系详解
全国计算机等级考试(NCRE)证书体系为中学生提供了一个系统学习和提升计算机能力的平台。本文将详细介绍 NCRE 证书的构成,帮助中学生了解 NCRE 证书的级别和内容,规划未来职业发展。 一、NCRE 证书体系概述 NCRE 证书共分为四个级…...
嵌入式之总线
嵌入式系统中的总线(Bus)是指用于连接各种组件(如处理器、存储器、外设等)的通信通道。总线的设计和实现对嵌入式系统的性能、功耗和扩展性有着重要影响。下面详细介绍嵌入式系统中的总线的概念、类型和特点。 一、总线的基本概念 总线是一种共享的通信路径,允许多个设备…...
如何在WPS打开的word、excel文件中,使用AI?
1、百度搜索:Office AI官方下载 或者直接打开网址:https://www.office-ai.cn/static/introductions/officeai/smartdownload.html 打开后会直接提示开始下载中,下载完成后会让其选择下载存放位置: 选择位置,然后命名文…...
Java 使用websocket
添加依赖 <!-- WebSocket 支持 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dependency>添加配置类 Configuration public class WebSocketConfig {B…...
MySQL 视图入门
一、什么是 MySQL 视图 1.1 视图的基本概念 在 MySQL 中,视图是一种虚拟表,它本身并不存储实际的数据,而是基于一个或多个真实表(基表)的查询结果集。可以把视图想象成是一个预定义好的查询语句的快捷方式。当你查询…...
【设计模式】 代理模式(静态代理、动态代理{JDK动态代理、JDK动态代理与CGLIB动态代理的区别})
代理模式 代理模式是一种结构型设计模式,它提供了一种替代访问的方法,即通过代理对象来间接访问目标对象。代理模式可以在不改变原始类代码的情况下,增加额外的功能,如权限控制、日志记录等。 静态代理 静态代理是指创建的或特…...
高考或者单招考试需要考物理这科目
问题:帮忙搜索一下以上学校哪些高考或者单招考试需要考物理这科目的 回答: 根据目前获取的资料,明确提及高考或单招考试需考物理的学校为湖南工业职业技术学院,在部分专业单招时要求选考物理;其他学校暂未发现明确提…...
《A++ 敏捷开发》- 16 评审与结对编程
客户:我们的客户以银行为主,他们很注重质量,所以一直很注重评审。他们对需求评审、代码走查等也很赞同,也能找到缺陷,对提升质量有作用。但他们最困惑的是通过设计评审很难发现缺陷。 我:你听说过敏捷的结对…...
NutUI内网离线部署
文章目录 官网拉取源代码到本地仓库修改源代码打包构建nginx反向代理部署访问内网离线地址 在网上找了一圈没有写NutUI内网离线部署的文档,花了1天时间研究下,终于解决了。 对于有在内网离线使用的小伙伴就可以参考使用了 如果还是不会联系UP主:QQ:10927…...
【实战篇】【深度介绍 DeepSeek R1 本地/私有化部署大模型常见问题及解决方案】
引言 大家好!今天我们来聊聊 DeepSeek R1 的本地/私有化部署大模型。如果你正在考虑或者已经开始了这个项目,那么这篇文章就是为你准备的。我们会详细探讨常见问题及其解决方案,帮助你更好地理解和解决在部署过程中可能遇到的挑战。准备好了…...
数据结构--双向链表,双向循环链表
双向链表的头插,尾插,头删,尾删 头文件:(head.h) #include <string.h> #include <stdlib.h> typedef…...
Qt学习(六) 软件启动界面 ,注册表使用 ,QT绘图, 视图和窗口绘图,Graphics View绘图框架:简易CAD
一 软件启动界面 注册表使用 知识点1:这样创建的界面是不可以拖动的,需要手动创建函数来进行拖动,以下的3个函数是从父类继承过来的函数 virtual void mousePressEvent(QMouseEvent *event);virtual void mouseReleaseEvent(QMouseEvent *eve…...
java练习(36)
ps:题目来自力扣 给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 . 和 * 的正则表达式匹配。 . 匹配任意单个字符* 匹配零个或多个前面的那一个元素 所谓匹配,是要涵盖 整个 字符串 s 的,而不是部分字符串。 class Solution {publ…...
go 网络编程 websocket gorilla/websocket
在 Go 语言中,你可以使用标准库中的 net/http 包和第三方库 gorilla/websocket 来实现一个 WebSocket 服务器。gorilla/websocket 库提供了对 WebSocket 协议的高级抽象,使得处理 WebSocket 连接变得相对简单。 package mainimport ("fmt"&qu…...
deepseek与其他大模型配合组合
DeepSeek与其他大模型的配合组合,展现了其在多个领域中的强大应用潜力和灵活性。以下是对DeepSeek与其他大模型配合组合的详细分析: 一、DeepSeek与华知大模型的组合 背景介绍: 华知大模型是同方知网与华为联手打造的,具备全学科…...
【Linux网络编程】IP协议格式,解包步骤
目录 解析步骤 1.版本字段(大小:4比特位) 2.首部长度(大小:4比特位)(单位:4字节) 🍜细节解释: 3.服务类型(大小:8比特…...
Unity 位图字体
下载Bitmap Font Generator BMFont - AngelCode.com 解压后不用安装直接双击使用 提前设置 1、设置Bit depth为32 Options->Export options 2、清空所选字符 因为我们将在后边导入需要的字符。 Edit->Select all chars 先选择所有字符 Edit->Clear all chars i…...
Linux 网络与常用操作(适合开发/运维/网络工程师)
目录 OSI 七层协议简介 应用层 传输层 Linux 命令!!! 1. ifconfig 命令 简介 1. 查看网络地址信息 2. 指定开启、或者关闭网卡 3. 修改、设置 IP 地址 4. 修改机器的 MAC 地址信息 5. 永久修改网络设备信息 2. route 路由命令 …...
指定定网卡名称
一、PCIe网卡名称指定 原理:利用udev规则匹配PCIe设备的硬件特征(如总线位置、MAC地址等),覆盖默认命名规则 4 。 步骤: 获取设备信息: Bash udevadm info -a -p /sys/class/net/<原设备名> # 如e…...
linux 安装启动zookeeper全过程及遇到的坑
1、下载安装zookeeper 参考文章:https://blog.csdn.net/weixin_48887095/article/details/132397448 2、启动失败 1、启动失败JAVA_HOME is not set and java could not be found in PATH 已安装 JAVA 配置了JAVA_HOME,还是报错解决方法:参考…...
RD-搭建测试环境
测试团队职责 环境验证:确保开发部署的测试环境可访问,页面/接口无阻塞问题; 配置检查**:核对数据库连接、接口域名、HT证书等关键配置; 数据准备**:导入基线数据,隔离测试与生产数据࿱…...
MySQL数据库——表的约束
1.空属性(null/not null) 两个值:null(默认的)和not null(不为空) 数据库默认字段基本都是字段为空,但是实际开发时,尽可能保证字段不为空,因为数据为空没办法…...
ArcGIS Pro进行坡度与坡向分析
在地理信息系统中,坡度分析是一项至关重要的空间分析方法,旨在精确计算地表或地形的坡度,为地形特征识别、土地资源规划、环境保护、灾害预警等领域提供科学依据。本文将详细介绍如何利用ArcGIS Pro这一强大的地理信息系统软件,进…...
【MySQL常见疑难杂症】MySQL数据库底层图例
● Connectors(连接者):指的是不同语言中与SQL的交互,从图3-1中可以看到目前流行的语言都支持MySQL客户端连接。 ● Connection Pool(连接池):管理缓冲用户连接、线程处理等需要缓存的需求。…...
nats集群搭建
本次使用三台机器搭建nats集群,ip分别为192.168.20.7、192.168.20.8、192.168.20.10,预先在三台机器上装好nats,版本为0.0.35。 1. 在192.168.20.7机器上操作,配置server.conf # 为节点设置唯一的名称 server_name: node1 port: …...
