Google Sheets递归Lambda笛卡尔积公式解析求助
笛卡尔积数组生成公式拆解与原理讲解
背景
出于学习需求,我需要拆解下面这个生成多列所有组合笛卡尔积的公式,理解其运行逻辑。这个公式大量使用递归Lambda,我无法理清其中的逻辑,因此寻求详细解释。
代码示例
=let( table, A2:C, blank, iferror(1/0), first_, lambda(array, tocol(choosecols(array, 1), true)), rest_, lambda(n, choosecols(table, sequence(1, columns(table) - n, n + 1))), wrap_, lambda(array, wrapCount, wraprows(tocol(array, 1), wrapCount)), cartesian_, lambda(a, b, wrap_( byrow(a, lambda(row, reduce(blank, sequence(rows(b)), lambda(acc, i, { acc, row, chooserows(b, i) } ) ) ) ), columns(a) + columns(b) ) ), iterate_, lambda( self, a, b, if(iserror(b), a, self(self, cartesian_(a, first_(b)), rest_(columns(a) + 1)) ) ), iterate_(iterate_, first_(table), rest_(1)) )
输入数据
对应公式中table变量的A至C列数据:
| 产品 | 国家 | 日期 |
|---|---|---|
| ABC001 | UK | 9/4/2023 |
| US | 9/11/2023 | |
| AU | 9/18/2023 | |
| 9/25/2023 |
输出数据
生成的笛卡尔积结果:
| 产品 | 国家 | 日期 |
|---|---|---|
| ABC001 | UK | 9/4/2023 |
| ABC001 | UK | 9/11/2023 |
| ABC001 | UK | 9/18/2023 |
| ABC001 | UK | 9/25/2023 |
| ABC001 | US | 9/4/2023 |
| ABC001 | US | 9/11/2023 |
| ABC001 | US | 9/18/2023 |
| ABC001 | US | 9/25/2023 |
| ABC001 | AU | 9/4/2023 |
| ABC001 | AU | 9/11/2023 |
| ABC001 | AU | 9/18/2023 |
| ABC001 | AU | 9/25/2023 |
公式拆解与运行原理
1. 基础变量定义
table:直接指定数据源范围为A2:C,对应输入的三列数据。blank:用iferror(1/0)生成错误值,作为reduce函数的初始空容器(数组拼接需要初始空值占位)。first_:提取输入数组的第一列,并用tocol(..., true)过滤空值,返回非空的单列数组。比如输入的产品列处理后得到["ABC001"],国家列得到["UK","US","AU"]。rest_:根据传入的参数n,从第n+1列开始提取剩余所有列。比如rest_(1)返回原表格的第2、3列(国家和日期列),rest_(2)返回第3列(日期列);当n等于总列数时会返回错误值,作为递归终止的判断条件。wrap_:先把输入数组扁平化(tocol(array,1)忽略空值),再用wraprows按指定列数重新组合成二维表格,用于把笛卡尔积生成的扁平数据恢复成规整的多列格式。
2. 笛卡尔积生成核心:cartesian_
这个Lambda函数负责生成两个数组a和b的笛卡尔积:
- 用
byrow(a, ...)遍历a的每一行; - 对
a的每一行,用reduce遍历b的所有行(sequence(rows(b))生成行号序列),每次把当前a的行和b的第i行拼接,累加到acc(初始为blank); - 所有行处理完后得到扁平的一维数组,再用
wrap_转换成列数为columns(a)+columns(b)的二维表格,也就是a和b的笛卡尔积结果。
比如a是["ABC001"](1列1行),b是["UK","US","AU"](1列3行),处理后会得到3行2列的数组:
ABC001 | UK ABC001 | US ABC001 | AU
3. 递归迭代处理所有列:iterate_
这是实现多列笛卡尔积的关键递归Lambda:
- 参数
self代表函数自身,用于递归调用;a是当前已生成的笛卡尔积结果;b是剩余未处理的列; - 判断
b是否为错误值:如果是,说明所有列处理完成,返回当前的a作为最终结果; - 如果
b有效,就调用self(递归),把a和b的第一列(first_(b))生成新的笛卡尔积,再传入rest_(columns(a)+1)作为新的剩余列,继续迭代。
4. 整体运行流程
- 初始调用
iterate_(iterate_, first_(table), rest_(1)):first_(table)是产品列的非空值["ABC001"],rest_(1)是国家+日期列; - 第一次递归:用
["ABC001"]和国家列的非空值生成3行2列的笛卡尔积,然后传入rest_(2)(日期列)继续迭代; - 第二次递归:用3行2列的数组和日期列的4个非空值生成12行3列的笛卡尔积,此时
rest_(3)会返回错误值(总列数是3,n+1=4超出范围); - 递归终止,返回最终的12行3列数组,也就是输出的结果。
内容的提问来源于stack exchange,提问作者Wesley Jeftha
相关产品推荐
相关产品推荐

