|
楼主 |
发表于 2022-6-3 08:52
|
显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用 · 内置多项VBA编程加强工具 ★ 免费下载 ★ ★ 使用手册★
第17个函数:REDUCE函数
REDUCE函数是这一系列里最后一个函数,是一个功能非常强大的循环函数,和Power Quqery里的List.Accumulate很相似。这个函数既可以循环返回单值,也可以将每步循环的结果显示出来,在实际应用中,叠加数组、变换表格样式等场景下应用非常多。思路上能用循环每个元素进行运算然后将结果堆叠起来解决的问题,差不多都可以考虑REDUCE函数。
REDUCE函数的语法如下:
=REDUCE([initial_value], array, lambda(accumulator, value)),第一参数为初始值,可以是单值也可以是数组;第二参数是要循环的数组,也可以只是用来控制循环次数的数组,REDUCE函数循环的次数由第二参数数组的元素数量来决定;第三参数是LAMBDA函数,确定第二参数需要执行的运算,并将运算结果形成下一步运算的初始值。
一般我自己习惯写成:REDUCE(初始值,循环的数组,LAMBDA(x,y,运算公式))这种方式,x代表每次循环时的初始值,每次循环后更新(值不一定更新,可以判断保留上步运算值),y代表循环数组中的每个元素。当然,你也可以使用其他数字分别代表初始值和循环数组的元素,比如说:REDUCE(初始值,循环的数组,LAMBDA(s,c,运算公式))等。但是如果涉及嵌套时,例如LAMBDA的运算公式里再涉及REDUCE函数、MAP函数等时,变量名称就别用同样的了,因为在REDUCE函数的LAMBDA函数体里面,s,c或x,y已经有特定含义了。
下面用一些简单例子来说明REDUCE函数用法:
下面的公式可以求A5:A6单元格区域数据的平方和:
- =REDUCE(0,A5:C6,LAMBDA(x,y,x+y^2))
复制代码
x的初始值是0,循环A5:A6单元格每个元素时,初始值x+y^2形成第二次循环时的初始值x。
就这个例子来说,目前帮助文件中的写法是不严谨,甚至可以说是错误的,帮助文件中是如此写的:
- =REDUCE(, A1:C2, LAMBDA(a,b,a+b^2))
复制代码
公式中省略了REDUCE函数的第一参数,之所以正确只是因为第一参数1的平方值仍是1。当REDUCE函数第一参数省略时,REDUCE函数在运算时会将第二参数的第一个值保留下来,不参与LAMBDA函数体里的运算。我们来看下面的说明。
我们将第二参数数组第一个元素改成7,按帮助文件的省略第一参数写法,最终函数返回结果是97:
- =REDUCE(,A16:C17,LAMBDA(x,y,x+y^2))
复制代码
从右侧的运算过程可以看出,由于省略了第一参数,因此第一次循环时7并没有参与平方运算,而是直接保留了下来,作为下一次循环的x,所以结果是97。
实际上,初始值写0就能得到正常运算结果139:
- =REDUCE(0,A25:C26,LAMBDA(x,y,x+y^2))
复制代码
第一参数不省略,循环第一个元素7时,7也参与了平方运算生成49,作为下一步循环的初始值x。
还有一个常见的例子是循环将一个字符串中的多个关键字替换成空,该功能可以使用以下函数完成:
- =REDUCE(A36,A39:A41,LAMBDA(x,y,SUBSTITUTE(x,y,)))
复制代码
REDUCE函数在循环A39:A41单元格每个元素时,都将当前循环的初始值x中的对应关键字用SUBSTITUTE函数替换成空。第一次循环时将“Excel”替换成空,第二次循环时的x已经是将“Excel”替换成空后的字符串了,再继续替换“人”为空。
除了替换成空之外,将替换关键词列表中的关键词替换成其他值:
- =REDUCE(A46,A49:A51,LAMBDA(x,y,SUBSTITUTE(x,y,VLOOKUP(y,A49:B51,2,))))
复制代码
上图中,A48:B51单元格区域时关键词和需要替换的值列表,A46单元格为初始字符串。在SUBSTITUTE函数的第三参数使用VLOOKUP(y,A49:B51,2,)返回对应B列的内容。
REDUCE函数第二参数为单元格区域时,LAMBDA函数循环元素时会保留单元格属性,可以使用ROW函数等提取行号,但是多层嵌套时可能失去该特性。还有使用INDEX函数等处理后也可能失去该特性:
如果只是&y,则不会有问题:
只是用offset,返回的还是个区域range,则可以使用row等函数:
index提取后,也是变成了普通数组,不是单元格引用了:
只用offset没有问题,y都是单元格引用:
再来看一个逆转字符串的例子:
- =REDUCE("",MID(A55,SEQUENCE(LEN(A55)),1),LAMBDA(x,y,y&x))
复制代码
用MID函数将A55单元格字符串按每个字符拆开,然后每次循环时都将这个字符放在x的左面连接起来。
下面的公式可以在每个大写字母前面加一个空格:
- =REDUCE(A61,CHAR(ROW($66:$91)),LAMBDA(x,y,SUBSTITUTE(x,y," "&y)))
复制代码
第二参数生成每个大写字母,然后SUBSTITUTE循环替代,替代时在y前面加上一个空格。例如循环到字母D,则将D替换成“ D”。
REDUCE函数的第二参数,可以只用来控制循环次数,实际不使用对应的值运算:
第二参数一个8个元素,所以REDUCE函数循环8次。如果你想循环足够多的次数还要节省字母,可以用类似=REDUCE(0,1:1,LAMBDA(x,y,x+1))
下面的公式,可以将字符串中连续的A或B最终替换成单个A或B:
- =REDUCE(A79,K79:K81&{"A","B"},LAMBDA(x,y,SUBSTITUTE(x,y&y,y)))
复制代码
其中第二参数部分K79:K81&{"A","B"}引用K79:K81这样的空单元格区域(足够多以控制足够的次数)形成下面的数组:
REDUCE函数循环这个数字,分别将A替换3次,B替换3次,每次替换时都把两个A替换成一个A,也即将y&y替换成y。
(下楼待续)。
|
-
-
评分
-
2
查看全部评分
-
|