ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
楼主: shaowu459

[分享] Microsoft 365:X檔案大揭秘

  [复制链接]

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-6-19 09:59 | 显示全部楼层
本帖已被收录到知识树中,索引项:LAMBDA
在编程时经常会有类似的算法:从第一个元素或最后一个元素开始往后或往前遍历,遍历到符合条件的位置时,对该位置之前或之后的已遍历元素进行运算,然后返回对应值。使用REDUCE函数的X,可以实现类似的用法,X就是已遍历元素的集合,不满足条件的时候逐个装入y,待满足条件后,对当前的X进行运算。

题目:找到下一个排列,下一个排列是指如果数组的所有排列从小到大排列后排在它后面的那个数。如果不存在下一个更大的排列,那么这个数必须重排为最小的排列。
例如:123的下一个排列是132,132是比123大的,且各位数字数量都和123的各位数字数量一致,也可以说是对123的各位数字进行重新组合,生成的大于123的最小数字 。类似地,231的下一个排列是312。而321的下一个排列是123,因为321不存在一个字典序更大的排列。更多示例如下:

图片.png
  1. =LET(s,LEFT(RIGHT(A2,SEQUENCE(LEN(A2)))),u,--CONCAT(REDUCE(,s,LAMBDA(x,y,LET(w,VSTACK(y,x),v,SORTBY(w,w>y,-1,w,1),IF(OR(y>=@x,x=""),w,VSTACK(@v,SORT(DROP(v,1)),"")))))),IF(u=A2,--CONCAT(SORT(s)),u))
复制代码
图片.jpg
首先数字最右侧开始取,倒序取出数字中的每一个数字;然后判断当前数字是不是大于上一个装入X的数字,如果是的话,当前的y和X中大于y的最小值交换,然后交换后的X进行排序。具体算法可以参考:https://blog.csdn.net/m0_63988748/article/details/125598526。核心在于X存储了已经遍历过的元素。

如果不用REDUCE函数,也可以用其他方法实现下一个排列的计算,例如:
  1. =LET(s,MID(0&A2,ROW($1:11),1),t,XMATCH(1=1,s<DROP(s,1),,-1),w,DROP(s,t-1),v,SORTBY(w,w>@w,-1,w,1),--IFERROR(CONCAT(TAKE(s,t-1),@v,SORT(DROP(v,1))),CONCAT(SORT(s))))
复制代码

图片.jpg

评分

3

查看全部评分

TA的精华主题

TA的得分主题

发表于 2023-6-27 12:24 | 显示全部楼层
牛逼,顶你!

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-7-29 09:04 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
使用x模拟堆栈,示例详见链接:
https://club.excelhome.net/threa ... tml?_dsign=0d2c4430

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-7-31 19:37 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖最后由 shaowu459 于 2023-7-31 19:38 编辑

x为字符串,每次循环时根据判断标准更新x。

以下是一个展开字符串的小题,例如将“3(a)2(2(bc))”展开,括号内的部分按左括号左侧的数字次数展开。

图片.jpg
参考公式:
  1. =REDUCE("",MID(A2,ROW($1:99),1),LAMBDA(x,y,LET(s,TAKE(TEXTSPLIT(x,"(",")"),-1),IF(y=")",TEXTBEFORE(x,")",-1)&REPT(INDEX(s,2),@s),x&IF(COUNT(-y)*ISERR(-RIGHT(x)),")",)&y))))
复制代码
图片.png

上述公式从左到右遍历A2单元格的每个字符:
1)如果是右括号,则提取x最后一个“)”右侧的待展开字符串和数字并展开,展开后的字符串连接在x最后一个“)”左侧的字符串上;
2)如果不是右括号,则直接将当前字符连接在x右侧。

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-8-2 22:40 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
使用当前y值生成新值,这个新值和x中已有元素进行某些规则的匹配,若x中已存在则保留x不变,否则将当前y产生的新值堆叠在x后方。
W`W)KA5ECH1}JDJ$PS_LX53.png 图片.png

W`W)KA5ECH1}JDJ$PS_LX53.png
W`W)KA5ECH1}JDJ$PS_LX53.png
图片.png

数值归纳.rar

9.36 KB, 下载次数: 4

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-8-3 20:34 | 显示全部楼层
X模拟堆栈,符合条件入栈,满足条件弹出栈顶元素。

题目:判断字符串是否为有效括号。
已知:A列字符串只包括"("、")"、"["、"]"。不同类型括号也不可以交叉,例如([)]为无效括号。有效的括号指:左括号必须用相同类型的右括号闭合,左括号必须以正确的顺序闭合。
要求:判断A列字符串是否是有效的括号字符串,是返回TRUE,否返回FALSE。
图片.png

公式一:

  1. =@REDUCE(0,MID(A2,ROW($1:99),1),LAMBDA(x,y,IF(OR(y={"(";"["}),VSTACK(y,x),DROP(x,OR(@x&y={"()","[]"})))))=0
复制代码
图片.png
公式简要说明如下:
=@REDUCE(
    0,   初始值设定为0
    MID(A2, ROW($1:99), 1),    遍历A2单元格中的每个字符
    LAMBDA(x, y,
        IF(
            OR(y = {"("; "["}),   如果y是(或者[,则入栈
            VSTACK(y, x),         (或者[堆叠在x上方
            DROP(x, OR(@x & y = {"()", "[]"}))  后面先出,假设x栈顶是(或者[,y是)或者],则将栈顶元素出栈。
        )
    )
) = 0    如果所有括号都匹配有效,则最终x只剩下,也就是入栈的(或者[都有0或]匹配走了。所以最后判断x第一个元素是否是0。

公式二:
  1. =REDUCE(A2,{"()","[]"}&Z1:Z9,LAMBDA(x,y,SUBSTITUTE(x,y,)))=""
复制代码
图片.png

公式简要说明如下
=REDUCE(
    A2,        初始值A2字符串
    {"()", "[]"} & Z1:Z9,       将两个括号的行数组和一列空单元格连接,生成9行2列的数组,将()和[]各重复9次用于替换
    LAMBDA(x, y, SUBSTITUTE(x, y, ))    循环将()和[]替换成空
) = ""         如果括号都是有效的,则A2单元格字符串可以被替换成空

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-8-7 10:35 | 显示全部楼层
将原始数据作为x的初始值,随着循环逐渐将x顶端的数据逐行drop掉(类似出栈)。


下图A:B列为原始数据,要求把缺失的号码填上,编号应从1开始用,并连续。填充后的效果如图右侧:
图片.png

参考公式(其他朋友还有更简短的公式):
  1. =REDUCE(+A2:B19,B2:B19,LAMBDA(x,y,VSTACK(DROP(x,1),HSTACK(@x,IF(y,y,MIN(IF(ISNA(MATCH(ROW(1:19),TOCOL(x/(TAKE(x,,1)=@x)),)),ROW(1:19))))))))
复制代码
图片.png

公式特点说明:
1)公式中没有使用SUM((A$2:s=s)*(B$2:x=0))从上到下数空单元格数量,然后从未出现的编号中提取对应数值的方法,而是采用类似“栈”的方法实现。
2)将A2:B19单元格区域作为x初始值,之所以写成+A2:B19是要将单元格区域转化为数组,方便后续使用@x提取x左上角的值。
3)REDUCE函数第二参数不管是循环A列还是B列的值,都难以避免使用OFFSET函数提取左侧的ID或者右侧的NO。观察到,使用@x可以提取ID,每次循环DROP掉一行,再使用@x仍然可以提取下次循环对应的ID,因此在公式中循环B列值作为y,这样提取每次循环时的ID可以直接用@x,每次循环时的NO直接使用y即可。
4)每次循环时将x首行去掉,并在下面增加{ID,NO}的数组,循环完毕,x初始值也会都被去掉,剩下的数组就是所求。





评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2023-8-7 10:49 | 显示全部楼层
x/(TAKE(x,,1)=@x),这个太绝了。

TA的精华主题

TA的得分主题

发表于 2023-8-7 16:16 | 显示全部楼层
=REDUCE(+A2:B19,B2:B19,LAMBDA(x,y,VSTACK(DROP(x,1),HSTACK(@x,IF(y,y,MATCH(,FREQUENCY(-(x=@x)*DROP(x,,1),-ROW(1:19)),))))))
LOG1.png

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-8-7 17:14 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖最后由 shaowu459 于 2023-8-7 17:21 编辑
cutecpu 发表于 2023-8-7 16:16
=REDUCE(+A2:B19,B2:B19,LAMBDA(x,y,VSTACK(DROP(x,1),HSTACK(@x,IF(y,y,MATCH(,FREQUENCY(-(x=@x)*DROP(x, ...

感谢跟帖支持
后部分处理也可以用UNIQUE函数:
  1. =REDUCE(+A2:B19,B2:B19,LAMBDA(x,y,VSTACK(DROP(x,1),HSTACK(@x,IF(y,y,@UNIQUE(VSTACK(ROW(1:19),TOCOL(x/(TAKE(x,,1)=@x))),,1))))))
复制代码
但就这个问题来说,不使用REDUCE函数的这种方法,群里还有一些比较短的公式(核心用UNIQUE+VSTACK组合,MAP一下自动溢出或下拉均可),因为跟这个帖的主题关系不大,就不一一列示了。


评分

1

查看全部评分

您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-5-21 17:40 , Processed in 0.045177 second(s), 9 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表