The*_*ter 4 lambda google-sheets space-complexity google-sheets-formula named-function
=SUM(SEQUENCE(10000000))
Run Code Online (Sandbox Code Playgroud)
上面的公式最多可以对 1000 万个虚拟数组元素进行求和。根据这个问答我们知道1000万是极限。现在,如果使用 Lambda 辅助函数将其实现为 Lambda REDUCE:
=REDUCE(,SEQUENCE(10000000),LAMBDA(a,c,a+c))
Run Code Online (Sandbox Code Playgroud)
我们得到,
尝试计算此公式时已达到计算限制
官方文档说
这可能在两种情况下发生:
- 公式的计算时间太长。
- 它使用了太多内存。
要解决此问题,请使用更简单的公式来降低复杂性。
所以,它说原因是空间和时间复杂性。但是抛出这个错误的确切空间是多少呢?这是如何确定的?
在REDUCE上面的函数中,虚拟数组的限制约为 66k:
=REDUCE(,SEQUENCE(66660),LAMBDA(a,c,a+c))
Run Code Online (Sandbox Code Playgroud)
但是,如果我们删除添加条件并使其仅返回当前值c,则允许的虚拟数组大小似乎会增加到 190k:
=REDUCE(,SEQUENCE(190000),LAMBDA(a,c,c))
Run Code Online (Sandbox Code Playgroud)
之后它会抛出一个错误。那么,这里的内存限制是由哪些因素决定的呢?我认为这是内存限制,因为它几乎在几秒钟内抛出错误。
如果您受到此问题的影响,您可以向 Google 发送反馈:
22 年 10 月更新(MaxMarkhov 提供)
现在该限制提高了 10 倍,达到 190 万1999992。这仍然不到非 lambda 公式的 1000 万个虚拟数组限制的 1/5,但比以前好得多。此外,非 lambda 公式的限制不会随着运算次数的增加而减少。但 lambda 辅助公式限制仍然会随着操作次数的增加而减少。因此,尽管它高出 10 倍,但这仅意味着 lambda 内部需要大约 5 个额外操作(见下表)。
部分答案
我们知道,事实上,以下因素决定了滚轮的计算极限:
LAMBDA()函数调用1 运算的基数似乎是199992 1 2 ( =REDUCE(,SEQUENCE(199992),LAMBDA(a,c,c)))。但是对于零操作或无操作(=REDUCE(,SEQUENCE(10000000),LAMBDA(a,c,0))),内存限制要高得多,但您仍然会遇到时间限制。我们还知道操作次数是一个因素,因为
=REDUCE(,SEQUENCE(66664/1),LAMBDA(a,c,a+c))失败=REDUCE(,SEQUENCE(66664),LAMBDA(a,c,a+c))作品。=REDUCE(,SEQUENCE(66664),LAMBDA(a,c,a+c+0))失败请注意,操作数的大小并不重要。如果=REDUCE(,SEQUENCE(39998),LAMBDA(a,c,a+c+0))有效,=REDUCE(,SEQUENCE(39998),LAMBDA(a,c,a+c+100000))也将有效。
对于 lambda 函数内操作数量的每次增加,允许的最大数组大小都会下降2n-1(感谢@OlegValter,实际上发现这里有一个因子倍数):
| 最大序列 | 操作数 (在 lambda 内) |
减少 (从199992开始) |
公式 |
|---|---|---|---|
| 199992 | 1 | 1 | 减少(,序列(199992),LAMBDA(a,c,c)) |
| 66664 | 2 | 1/3 | 减少(,序列(66664),LAMBDA(a,c,a + c)) |
| 39998 | 3 | 1/5 | 减少(,序列(39998),LAMBDA(a,c,a + c + 10000)) |
| 28570 | 4 | 1/7 | 减少(,序列(28570),LAMBDA(a,c,a + c + 10000 + 0)) |
函数之外的操作LAMBDA 也很重要。例如,=REDUCE(,SEQUENCE(199992/1),LAMBDA(a,c,c))会由于额外的/1操作而失败,但您只需要每次操作将数组大小线性减少 1 或 2,即,这=REDUCE(,SEQUENCE(199990/1),LAMBDA(a,c,c))将起作用3。
此外,LAMBDA函数调用本身的成本更高。因此,重构代码并不能消除内存限制,而是进一步减少内存限制。例如,如果您的代码使用LAMBDA(a,c,(a-1)+(a-1)),如果您添加另一个像这样的 lambda: LAMBDA(a,c,LAMBDA(aminus,aminus+aminus)(a-1)),则错误的数组元素比以前少得多(减少了约 20%)。LAMBDA比重复调用要贵得多。
还有许多其他因素在起作用,尤其是其他LAMBDA功能。谷歌稍后可能会改变对这些任意限制的看法。但这是一个开始。
LAMBDA本身不受限制。您可以随心所欲地嵌套。仅 LAMBDA 辅助函数受到限制。(归功于玩家0)
本身不使用LAMBDA(辅助函数)的命名函数不受相同的限制。但它们受到最大递归限制。
另一种解决方法是避免使用lambdaasarrayformula并使用自动填充或拖动填充功能,方法是使 lambda 函数每个函数仅返回一个值。请注意,这实际上可能会使您的工作表变慢。但显然,谷歌对此表示同意——多个单独的调用而不是单个数组调用。例如,我在这里编写了一个排列函数来获取所有排列的列表。虽然它抱怨具有超过 6 个项目的数组的“内存限制”,但它可以通过相对范围的自动填充/拖动填充/复制+粘贴轻松工作。
| 归档时间: |
|
| 查看次数: |
1151 次 |
| 最近记录: |