reduce进阶用法

一:reduce介绍

1.1:基本语法

array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
// array:你要操作的数组
// function:用来处理数组每个元素的回调函数
// initialValue:可选的初始值,可以不写
// 回调函数里有这些参数
// total:累计值。第一次是初始值,之后是上一次循环的结果
// currentIndex:当前处理的数组元素
// arr:当前正在处理的整个数组,也可以忽略

1.2:工作流程

1.设置初始值:如果你给了initialValue,它会作为total的初始值;如果没给,数组的第一个元素会作为初始值
2.迭代处理:reduce从初始值开始(或者数组的第一个/第二个元素),逐个处理每个currentValue,并把结果累加到total
3.完成迭代:数组处理完了,reduce就会返回累加后的最终结果

1.3:求和案例

假设你有一个数组[1, 2, 3, 4],你想算出这个数组中所有数字的和
const sum = [1, 2, 3, 4].reduce(function(total, currentValue) {
 return total + currentValue;
}, 0);
console.log(sum); // 输出:10

二:基础使用场景

1.1:计算数组的总和

const prices = [5, 12, 3, 7, 10];
const totalAmount = prices.reduce((total, price) => total + price, 0);
console.log(totalAmount); // 输出:37

1.2:数组元素的拼接

const lyrics = ["I", "love", "coding", "with", "JavaScript"];
const sentence = lyrics.reduce((total, word) => total + " " + word);
console.log(sentence); // 输出:"I love coding with JavaScript"

1.3:找到数组中的最大值

const scores = [45, 85, 72, 93, 66];
const highestScore = scores.reduce((max, score) => Math.max(max, score), -Infinity);
console.log(highestScore); // 输出:93

三:进阶用法

1.1:扁平化数组

一个装满了小盒子的大盒子,而这些小盒子里又装着更小的盒子。你的任务是把所有的小盒子里的物品全部倒出来,放到一个平面上这就是“扁平化”操作
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:就像把大盒子一层层打开。
Array.isArray(currentValue):检查当前拿到的是否还是一个小盒子(数组)。
Flat(currentValue):如果是小盒子,再递归地把它打开,直到拿出所有物品(非数组元素)。
concat:把这些物品一个个放到我们铺开的平面上(结果数组)。

1.2:分割数组——分页显示商品列表

想象你在打包一批商品,每个包裹只能装固定数量的商品。当一个包裹装满时,你就开始打包下一个包裹。最终,你会得到一系列整齐的包裹,每个包裹里都有固定数量的商品。这就是我们要做的“分页显示”
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:就像在打包商品。
total[total.length - 1]:这是当前正在打包的包裹。
total[total.length - 1].length === size:检查当前包裹是否装满。
push:如果满了,开始一个新的包裹;如果没满,把商品继续装入当前包裹。

1.3:统计出现次数

想象你在统计每个用户点击了多少次按钮,就像在记录每个用户按下不同按钮的次数。每次用户点击按钮,你就在一个记录本上对应的按钮旁边记下一笔,最后你就可以知道每个按钮被点击了多少次
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:就像在帮你统计每个事件的发生次数。
total[currentValue]:这是记录本上对应事件的计数。
total[currentValue] || 0:如果这个事件还没被记录过,就初始化为0。
+1:每次事件发生,就在对应的计数上加1。

1.4:查找元素位置

想象你在一堆订单中寻找那些出了问题的订单(比如状态为“异常”),就像在一份名单中标记出所有异常订单的位置,以便后续处理
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:就像在浏览订单列表,每找到一个符合条件的订单,就记下它的位置。
currentValue.status === val:检查当前订单是否是“异常”状态。
push(currentIndex):如果是异常订单,就把它的位置(索引)记录下来

1.5:组合函数——订单折扣计算

想象你在为用户计算订单总价,这个过程就像在制作一道美味的菜肴,需要按顺序添加各种配料(折扣、会员优惠、税费)。每一步都对最终的味道(价格)有影响,最后得到的是用户需要支付的总价。
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:这里的数组就像一系列步骤,每一步都对订单总价进行处理。
reduce:依次执行每个步骤,把当前的价格传给下一个处理函数。
100:初始的订单价格。
finalPrice:经过所有处理后的最终订单价格。

1.6:数组去重——数据清洗中的重复项去除

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.includes(currentValue):检查当前元素是否已经存在于结果数组中。
total:如果当前元素已经存在,就跳过;否则,把它加到结果数组中。

1.7:计算平均值

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.2
reduce:就像一个评分收集器,遍历每个用户的评分。
total += currentValue:把每个评分累加到总分里。
if (currentIndex === array.length - 1):在最后一个评分加完后,计算平均值。
total / array.length:总分除以评分人数,得到平均分。 • reduce:就像一个评分收集器,遍历每个用户的评分。
total += currentValue:把每个评分累加到总分里。
if (currentIndex === array.length - 1):在最后一个评分加完后,计算平均值。
total / array.length:总分除以评分人数,得到平均分。

1.8:找最大值和最小值

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)); // 输出:120
Max函数:通过遍历数组,记住当前看到的最大值。
Min函数:同样遍历数组,记住当前看到的最小值。
reduce:在遍历过程中比较每个值,并更新最大值或最小值

1.9 URL 参数解析——处理用户请求中的查询参数

搜索功能,当用户在搜索框中输入条件并提交时,URL会包含这些查询参数。你需要把这些参数拆解开,放到一个对象里,这样你就可以用它们来执行搜索查询。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中的问号或其他特殊符号,留下纯参数部分。
split("&"):将参数字符串按“&”分隔成一个数组,每个元素是一个“key=value”的形式。
reduce:遍历这个数组,把每个“key=value”解析成键值对,存入一个对象中。
decodeURIComponent(val):对参数值进行解码,以防止URL编码问题

2.0 URL 参数序列化——生成API请求参数

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]对,方便遍历。
reduce:遍历每个参数对,将它们拼接成“key=value”的形式,并用“&”连接。
encodeURIComponent(currentValue[1]):对参数值进行编码,确保特殊字符在URL中合法。
replace(/&$/, ""):去掉最后一个多余的“&”符号,使查询字符串格式正确

2.1:对象分组——按属性分组用户数据

用户的某个属性(比如年龄)将他们分组,这样可以更方便地进行统计和分析。reduce方法就像一个分类器,帮你把用户按照指定的属性归类到不同的组里
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:就像在整理用户数据,根据指定的属性(比如年龄)将用户归类。
total[currentValue[key]]:检查当前分类组是否已经存在,如果不存在,就创建一个新的数组来存放这一组用户。
push(currentValue):将用户添加到对应的分组中。

2.2: 创建查找表——快速查找产品信息

根据产品ID就能快速找到对应的产品信息。reduce方法可以帮你把产品数组转换为这样的查找表
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);
/*
输出:
{
  '1': { id: 1, name: 'Laptop', price: 999 },
  '2': { id: 2, name: 'Phone', price: 699 },
  '3': { id: 3, name: 'Tablet', price: 499 }
}
*/
reduce:遍历产品数组,逐一处理每个产品。
total[currentValue[key]] = currentValue:将产品的ID作为查找表的键,产品的详细信息作为对应的值,存入查找表。
total:最终形成一个以产品ID为键,产品信息为值的对象,方便快速查找

2.3:合并数组为对象——将表单字段与值配对

字段名和用户输入的值配对,形成一个对象,以便提交给后端处理。reduce方法可以帮你将这两个数组合并成一个对象
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,逐一处理每个字段。
total[currentValue] = arr2[index]:将字段名作为对象的键,将对应的用户输入值作为值,添加到对象中。
index:通过索引匹配字段名和对应的输入值。
  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python进阶函数是指一些高级特性和用法,它们可以进一步提高代码的复用性、可读性和效率。以下是一些常见的Python进阶函数及其用法: 1. 匿名函数(lambda函数):使用lambda关键字定义的匿名函数可以简洁地定义一些简单的函数。例如,lambda x: x**2表示一个接受参数x并返回x的平方的匿名函数。 2. map()函数:map()函数用于将一个函数应用到一个可迭代对象的每个元素上,并返回一个新的可迭代对象。例如,map(lambda x: x**2, [1, 2, 3, 4])将返回一个包含每个元素平方值的列表。 3. filter()函数:filter()函数用于根据指定条件过滤可迭代对象中的元素,并返回一个新的可迭代对象。例如,filter(lambda x: x > 0, [-1, 0, 1, 2])将返回一个包含大于0的元素的列表。 4. reduce()函数:reduce()函数用于对可迭代对象中的元素进行累积操作,并返回一个结果。需要先从`functools`模块导入。例如,reduce(lambda x, y: x+y, [1, 2, 3, 4])将返回10,表示1+2+3+4。 5. zip()函数:zip()函数用于将多个可迭代对象的对应元素打包成元组,然后返回一个新的可迭代对象。例如,zip([1, 2, 3], ['a', 'b', 'c'])将返回[(1, 'a'), (2, 'b'), (3, 'c')]。 6. enumerate()函数:enumerate()函数用于为可迭代对象中的元素添加索引,并返回一个新的可迭代对象。例如,enumerate(['a', 'b', 'c'])将返回[(0, 'a'), (1, 'b'), (2, 'c')]。 7. sorted()函数:sorted()函数用于对可迭代对象进行排序,并返回一个新的列表。例如,sorted([3, 1, 2])将返回[1, 2, 3]。 8. any()和all()函数:any()函数用于判断可迭代对象中是否存在至少一个为真的元素;all()函数用于判断可迭代对象中的所有元素是否都为真。例如,any([True, False, True])将返回True,而all([True, False, True])将返回False。 这些是Python进阶函数的一些例子,它们可以帮助你更高效地编写代码,增加代码的灵活性和可读性。当然,还有很多其他的进阶函数和技巧可以在Python文档和其他教程中学习到。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值