array.reduce(function(total, currentValue, currentIndex, arr), initialValue)array:你要操作的数组。
initialValue:可选的初始值,可以不写。
arr:当前正在处理的整个数组,也可以忽略。
const sum = [1, 2, 3, 4].reduce(function(total, currentValue) { return total + currentValue; }, 0); console.log(sum); // 输出:10看,这段代码就是在做加法,reduce从0开始,每次把当前数字加到total上,最后得到10。
const prices = [5, 12, 3, 7, 10]; const totalAmount = prices.reduce((total, price) => total + price, 0); console.log(totalAmount); // 输出:37这里reduce就是在帮你“算账”,它从0开始,每次加上一个商品的价格,最后得到总金额37。
const lyrics = ["I", "love", "coding", "with", "JavaScript"]; const sentence = lyrics.reduce((total, word) => total + " " + word); console.log(sentence); // 输出:"I love coding with JavaScript"在这个例子中,reduce把每个词拼接在一起,最终形成了这句优美的话:"I love coding with JavaScript"。
const scores = [45, 85, 72, 93, 66]; const highestScore = scores.reduce((max, score) => Math.max(max, score), -Infinity); console.log(highestScore); // 输出:93在这个比喻中,reduce方法帮你把所有同学的分数都比了一遍,最后选出分数最高的那个,成为“最强王者”。
function Flat(arr = []) { return arr.reduce((total, currentValue) => total.concat(Array.isArray(currentValue) ? Flat(currentValue) : currentValue), []); } const nestedFiles = [0, 1, [2, 3], [4, 5, [6, 7]], [8, [9, 10, [11, 12]]]]; console.log(Flat(nestedFiles)); // 输出:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]reduce:就像把大盒子一层层打开。
concat:把这些物品一个个放到我们铺开的平面上(结果数组)。
function Chunk(arr, size) { return arr.length ? arr.reduce((total, currentValue) => (total[total.length - 1].length === size ? total.push([currentValue]) : total[total.length - 1].push(currentValue), total), [[]]) : []; } const products = [1, 2, 3, 4, 5]; console.log(Chunk(products, 2)); // 输出:[[1, 2], [3, 4], [5]]reduce:就像在打包商品。
push:如果满了,开始一个新的包裹;如果没满,把商品继续装入当前包裹。
function Counting(arr) { return arr.reduce((total, currentValue) => { total[currentValue] = (total[currentValue] || 0) + 1; return total; }, {}); } const userActions = ['click', 'scroll', 'click', 'hover', 'click']; console.log(Counting(userActions)); // 输出:{ 'click': 3, 'scroll': 1, 'hover': 1 }reduce:就像在帮你统计每个事件的发生次数。
+1:每次事件发生,就在对应的计数上加1。
function Position(arr, val) { return arr.reduce((total, currentValue, currentIndex) => { if (currentValue.status === val) { total.push(currentIndex); } return total; }, []); } const orders = [ { id: 1, status: 'completed' }, { id: 2, status: 'pending' }, { id: 3, status: 'exception' }, { id: 4, status: 'exception' } ]; console.log(Position(orders, 'exception')); // 输出:[2, 3]reduce:就像在浏览订单列表,每找到一个符合条件的订单,就记下它的位置。
push(currentIndex):如果是异常订单,就把它的位置(索引)记录下来。
const addDiscount = (x) => x - 5; const applyMemberDiscount = (x) => x * 0.9; const addTax = (x) => x + (x * 0.08); const composedFunctions = [addDiscount, applyMemberDiscount, addTax]; const finalPrice = composedFunctions.reduce((total, currentValue) => currentValue(total), 100); console.log(finalPrice);composedFunctions:这里的数组就像一系列步骤,每一步都对订单总价进行处理。
finalPrice:经过所有处理后的最终订单价格。
function Uniq(arr) { return arr.reduce((total, currentValue) => total.includes(currentValue) ? total : [...total, currentValue], []); } const rawData = [2, 1, 0, 3, 2, 1, 2]; console.log(Uniq(rawData)); // 输出:[2, 1, 0, 3]reduce:就像一个过滤器,遍历数组中的每个元素。
total:如果当前元素已经存在,就跳过;否则,把它加到结果数组中。
function Average(arr) { return arr.reduce((total, currentValue, currentIndex, array) => { total += currentValue; if (currentIndex === array.length - 1) { return total / array.length; } return total; }, 0); } const ratings = [4, 5, 3, 4, 5]; console.log(Average(ratings)); // 输出:4.2reduce:就像一个评分收集器,遍历每个用户的评分。
total / array.length:总分除以评分人数,得到平均分。
function Max(arr = []) { return arr.reduce((total, currentValue) => total > currentValue ? total : currentValue); } function Min(arr = []) { return arr.reduce((total, currentValue) => total < currentValue ? total : currentValue); } const prices = [120, 450, 210, 650, 380]; console.log(Max(prices)); // 输出:650 console.log(Min(prices)); // 输出:120Max函数:通过遍历数组,记住当前看到的最大价格。
reduce:在遍历过程中比较每个商品的价格,并更新最大值或最小值。
function ParseUrlSearch(str) { return str.replace(/(^\?)|(&$)/g, "").split("&").reduce((total, currentValue) => { const [key, val] = currentValue.split("="); total[key] = decodeURIComponent(val); return total; }, {}); } const url = 'key1=value1&key2=value2&key3=value3'; console.log(ParseUrlSearch(url)); // 输出:{ key1: 'value1', key2: 'value2', key3: 'value3' }replace(/(^?)|(&$)/g, ""):去掉URL中的问号或其他特殊符号,留下纯参数部分。
decodeURIComponent(val):对参数值进行解码,以防止URL编码问题。
function StringifyUrlSearch(search) { return Object.entries(search).reduce( (total, currentValue) => `${total}${currentValue[0]}=${encodeURIComponent(currentValue[1])}&`, Object.keys(search).length ? "?" : "" ).replace(/&$/, ""); } const params = { foo: "bar", baz: 42 }; console.log(StringifyUrlSearch(params)); // 输出:"?foo=bar&baz=42"Object.entries(search):将对象转换为一个二维数组,每个元素是一个[key, value]对,方便遍历。
replace(/&$/, ""):去掉最后一个多余的“&”符号,使查询字符串格式正确。
function Grouping(arr, key) { return arr.reduce((total, currentValue) => { if (!total[currentValue[key]]) { total[currentValue[key]] = []; } total[currentValue[key]].push(currentValue); return total; }, {}); } const users = [ { name: 'Alice', age: 25 }, { name: 'Bob', age: 30 }, { name: 'Charlie', age: 25 }, { name: 'Dave', age: 30 } ]; console.log(Grouping(users, 'age')); /* 输出: { '25': [{ name: 'Alice', age: 25 }, { name: 'Charlie', age: 25 }], '30': [{ name: 'Bob', age: 30 }, { name: 'Dave', age: 30 }] } */reduce:就像在整理用户数据,根据指定的属性(比如年龄)将用户归类。
push(currentValue):将用户添加到对应的分组中。
12. 创建查找表——快速查找产品信息function arrayToMap(arr, key) { return arr.reduce((total, currentValue) => { total[currentValue[key]] = currentValue; return total; }, {}); } const products = [ { id: 1, name: 'Laptop', price: 999 }, { id: 2, name: 'Phone', price: 699 }, { id: 3, name: 'Tablet', price: 499 }, ]; const productMap = arrayToMap(products, 'id'); console.log(productMap);/*
total:最终形成一个以产品ID为键,产品信息为值的对象,方便快速查找。
function Merge(arr1, arr2) { return arr1.reduce((total, currentValue, index) => { total[currentValue] = arr2[index]; return total; }, {}); } const fields = ['name', 'age', 'gender']; const values = ['Alice', 25, 'female']; console.log(Merge(fields, values)); // 输出:{ name: 'Alice', age: 25, gender: 'female' }reduce:遍历字段数组arr1,逐一处理每个字段。
index:通过索引匹配字段名和对应的输入值。
function isPalindrome(str) { return str.split('').reduce((total, currentValue, index, array) => { return total && currentValue === array[array.length - index - 1]; }, true); } const input = 'racecar'; console.log(isPalindrome(input)); // 输出:truesplit(''):将字符串分割成单个字符的数组。
total && currentValue === array[array.length - index - 1]:检查当前字符是否与对应位置的字符相同,如果全部匹配,则为回文。