用公式实现排列组合
创作者俱乐部成员
公式的表达能力越来越强了,原来下意识用宏解决的问题,现在似乎用公式也可以方便的完成,赞赞赞!!!
感觉现在的公式越来越像lisp的方言了,let、lambda的用法似乎可以参考scheme语言的教程。
下面是尝试用公式,做一个从X个数里取Y个的不重复的组合的方法:
遇到的问题:
IF这里只能嵌套着写两层,为什么用IFS替换成两个判断会报错?是不是bug啊,谁来帮忙试试
map之类的公式会遍历单元格,而不是遍历行,导致用图中这样连接成字符串的方法还简单点,否则不能用map还得再加一层lambda有点不习惯
💡 | =LET(f,LAMBDA(x,y,IF(y=1,x,IF(ROWS(x)=y,TEXTJOIN(",",,x),VSTACK(MAP(f(DROP(x,1),y-1),LAMBDA(i,TAKE(x,1)&","&i)),f(DROP(x,1),y))))),f(A1:A6,3)) |
大概解释一下公式:
总的框架是LET(f,LAMBDA(x,y,IF()),f(x,y)),这是个写递归的套路,用let给lambda表达式一个名称f(这样就不用像Excel那样必须使用名称管理器才能递归),if里先是递归的退出条件
第一层IF,y=1是指,要从数组x里取y个数,如果只取1个,直接返回x就行
第二层IF,ROWS(x)=y是指,如果x的行数等于y,那直接把x用逗号连起来返回就行
剩下的情况需要递归,总的框架是个VSTACK,里面分别是x里的当前行,选中、不选中两种情况
选中当前行,那么在剩下的行里需要选取的个数y就需要减1,这些选出来的行,前头都要加上当前行,MAP(f(DROP(x,1),y-1),LAMBDA(i,TAKE(x,1)&","&i))
不选中当前行,那么就是在剩下的行里再选y个,f(DROP(x,1),y)
把这两条路的结果vstack起来,就是结果