如何在Excel中构建由1D动态数组参数化的2D动态数组

How to build a 2D dynamic array parameterised by a 1D dynamic array in Excel

提问人:Leo 提问时间:10/25/2023 更新时间:10/25/2023 访问量:99

问:

有没有办法通过在Office 365 Excel中将多个动态数组连接在类似for的循环中创建动态数组?

这是一个 MWE(我的实际列比仅仅使用 .randarray

我试图实现的是下图中的单元格 B2:F4:screenshot of desired outcome

作为屏幕截图的公式...enter image description here

...并作为文本:

index: =SEQUENCE(,5)
desired: =RANDARRAY(3,5, B1#,B1#+1,TRUE)
workaround: =RANDARRAY(3,,B1,B1+1,TRUE)
attempt 1 (hstack): =HSTACK(RANDARRAY(3,,B1#,B1#+1,TRUE))
attempt 2 (bycol): =BYCOL(B$1#,LAMBDA(m,RANDARRAY(3,1,m,m+1,TRUE)))

我确实注意到(见屏幕截图)存在“嵌套数组”错误,这似乎很重要。我将不胜感激任何反馈、示例或澄清,即使答案是“2023 年不可能”。

Excel 动态数组

评论

1赞 DjC 10/25/2023
那么,您的“实际”和实际期望的输出是什么?所示特定问题的解决方案可能是,但这可能对您的实际数据有帮助,也可能没有帮助。=MAKEARRAY(3, 5, LAMBDA(r,c, RANDBETWEEN(c, c+1)))
0赞 DjC 10/25/2023
除了我上面的评论之外,您可以使用 with 来遍历一维数组的行或列。例如:INDEX()MAKEARRAY()=MAKEARRAY(3, COLUMNS(B1#), LAMBDA(r,c, RANDBETWEEN(INDEX(B1#,c), INDEX(B1#,c)+1)))
0赞 Leo 10/25/2023
@MayukhBhattacharya我觉得我的MWE有点令人困惑。我不想要空行。空行是错误。我想要的是像使用单个数组而不是使用拖动粘贴功能一样工作。desiredworkaround
1赞 Leo 10/25/2023
@DjC谢谢,是我缺少的功能!makearray

答:

3赞 VBasic2008 10/25/2023 #1

RANDARRAY应用于重复行

重复行

  • 这将“重复”行次数,导致(想象复制到)。3dB1:F1B2:F4
  • 然后它使用 和 与函数。dd+1RANDARRAY
=LET(data,B1#,rows,3,increment,1,
    d,IF(SEQUENCE(rows),data),
RANDARRAY(COLUMNS(d),rows,d,d+increment,1))

enter image description here

MAKEARRAY(类似于 DjC 在您的评论中的建议)

=LET(data,B1#,rows,3,increment,1,
MAKEARRAY(rows,COLUMNS(data),LAMBDA(r,c,
    LET(num,INDEX(data,c),
    RANDBETWEEN(num,num+increment)))))

评论

0赞 VBasic2008 10/25/2023
@MayukhBhattacharya 我越看它,我就越觉得我必须删除它。这与 OP 更简单的“解决方法”相同。
0赞 Leo 10/25/2023
@VBasic2008解决方法更简单,但这是一个计算时间更长的工作流,因此我很乐意在这里吃一些复杂性,以使我的所有依赖公式都是动态的。
1赞 Leo 10/25/2023
感谢@VBasic2008这回答了提出的问题,我认为它对社区很有用。这个答案对我不太有效,因为我的问题省略了一个重要的点:我真正需要使用的函数创建了一个列输出。我将输入一个单独的问题。
2赞 DjC 10/25/2023 #2

只是为了好玩,这里有一个解决方案,它通过使用定点组合器(p.s.我在reddit上偶然发现了这种方法):LAMBDA()LET()

=LET(
F, LAMBDA(X,a,b,c,[val],[num],
   LET(
   d, RANDARRAY(, COLUMNS(a), a, a+b, TRUE),
   v, IF(ISOMITTED(val), d, VSTACK(val, d)),
   n, IF(ISOMITTED(num), 1, num),
   IF(n<c, X(X, a, b, c, v, n+1), v))),
F(F, B1#, 1, 3))

需要明确的是,使用此方法在名称管理器中没有定义任何自定义函数。上述公式可以直接输入到任何单元格中。

结果:

recursive_let.png

解释:

通常,为了创建递归 lambda 函数,需要在名称管理器中定义它。例如,您可以使用以下公式定义名称:RANDMULT

=LAMBDA(array,increment,rows,[initial_value],[start],
   LET(
   d, RANDARRAY(, COLUMNS(array), array, array+increment, TRUE),
   v, IF(ISOMITTED(initial_value), d, VSTACK(initial_value, d)),
   n, IF(ISOMITTED(start), 1, start),
   IF(n<rows, RANDMULT(array, increment, rows, v, n+1), v)))

如您所见,如果未满足退出函数的条件,函数将再次调用自身。可选的 [initial_value] 和 [start] 参数是我们传递每次迭代结果的地方,直到迭代次数等于 rows 参数中指定的次数。这与 VBA 中的“For Next”循环基本相同。然后,该公式可以在任何单元格中使用。RANDMULT()RANDMULT()=RANDMULT(B1#, 1, 3)

不幸的是,如果我们尝试直接在名称管理器中(而不是在名称管理器)将相同的递归 lambda 函数定义为名称,它将返回错误。由于函数的约束,名称不能在自己的定义中按名称来指代自己......必须先完全定义它,然后才能使用。这就是定点运算器逻辑的用武之地。LET()#NAME?LET()

回到上面的第一个公式,当函数被定义时,它不是在自己的定义中再次调用自身,而是调用函数,该函数作为第一个参数传递给。完全定义函数后,将函数传递给自身以创建递归来使用它。F()X()F()F()

无论如何,我意识到这不是解决这个特定问题的最有效解决方案。我只是觉得这很有趣。干杯!:-)

评论

1赞 VBasic2008 10/25/2023
很棒的东西。让他们来吧。