NB 这个问题涉及一些功能,例如可选的 LAMBDA 参数和 ISOMITTED 函数,这些功能仅在 Beta 通道中可用(在撰写本文时)(更多信息此处)
我正在尝试在 Excel LAMBDA 函数中模仿 VBA 的参数数组,所以想要一个函数:
=ARRAY(arg_1, [arg_2], [arg_3], ...)
...返回数组
{arg_1, arg_2, arg_3, ...}
根据传递的参数数量动态调整大小。
如果我知道参数的数量,我可以像这样使用选择函数:
=CHOOSE(SEQUENCE(number_of_args), arg_1, arg_2, arg_3, ...))
但我不想将参数数量作为参数传递,我希望它是动态的。一个想法是使用
ISOMITTED(arg_n)
进行二分搜索以找到第一个缺失的参数。但这仍然硬编码了我的 ARRAY 函数的参数数量上限,更不用说创建一个讨厌的硬编码二叉树了。
使用 VBA 当然很容易:
Public Function ARRAYFROMARGS(ParamArray args()) As Variant
ARRAYFROMARGS = args
End Function
尽管这只能接受可以强制转换为变体的值,因此不能接受 lambda 或链接数据类型。这使得非 VBA 版本更加灵活。
这并不完全是您正在寻找的,但也许它会提供一些想法?如果我们可以一次取一个值而不是一个列表,那么我们可以使用转义字符 (\) 来让公式知道它不再需要任何值,而不是对参数进行限制,并使公式递归,并利用 MAKEARRAY 通过每个新条目扩展先前创建的数组。请注意,对于引用,第一个引用不得导致错误,因此必须为非空白。
ARRAY
=LAMBDA(val_1,
LAMBDA(val_2,
IF(
TYPE(val_2)=16,val_1,
ARRAY(
MAKEARRAY(ROWS(val_1)+1,COLUMNS(val_1),
LAMBDA(i,j,
IFERROR(INDEX(val_1,i,j),val_2)
)
)
)
)
)
)
正如我在问题中提到的,我找到了一种使用二分搜索来评估缺少多少参数的方法。但它确实涉及大量复制粘贴。因此,这里是通过查找丢失的第一个参数来评估传递的参数数量的代码:
标签 | 价值 |
---|---|
姓名 | 参数计数 |
范围 | 作业簿 |
评论 | 使用硬编码的二分搜索来查找第一个省略的参数,块最多为 63 |
参考 |
|
更容易复制版本这里
它是这样被称为
=ARGSCOUNT(arg_1, arg_2, ..., arg_63)
的,来自封闭的 LAMBDA。请注意,它最多需要 63 个可选参数,因为我的二叉树是对称的,因此必须是 2 的幂(0 个参数的情况下为负 1),并且命名引用的字符限制较低,约为 2000 个。但是,您可以多次调用它来自父函数并对结果求和,例如ARGSCOUNT(arg_1, ..., arg_63) + ARGSCOUNT(arg_64, ..., arg_126)
然后可以在第二个 LAMBDA 函数中使用该计数来构建数组:
标签 | 价值 |
---|---|
姓名 | 阵列 |
范围 | 作业簿 |
评论 | 从逗号分隔的参数创建一个数组,最多 130 个 |
参考 |
|
我知道这很讨厌,但这让你可以访问一个令人惊讶的简单功能:
=ARRAY(A1, A2, 3, "foo", "bar") // array of anything, dynamically sized
您甚至可以创建一个 LAMBDAS 数组来传递给诸如地图之类的东西:
=MAP(ARRAY(LAMBDA(x, x^2), LAMBDA(y, y+1)),LAMBDA(f, f(3)) // -> {9,4} i.e. 3^2, 3+1
...并且 vba ARRAYFROMARGS 函数不能将 LAMBDAS 作为参数。
为了完整性,现在可以使用
HSTACK
和 VSTACK
来实现,它们在帖子发布时尚未发布。但是,要定义您自己的可变参数函数,您需要遵循上述方法之一。
例如
=printf("{1} {2}!","Hello","World")
采用任意数量的后续参数定义如下https://codereview.stackexchange.com/questions/268446/printf1-2-in-excel-without-vba-lambda-functions-with-variable
=LAMBDA(
mask,
_0,[_1],[_2],[_3],[_4],[_5],[_6],[_7],[_8],[_9],[_10],[_11],[_12],[_13],[_14],[_15],[_16],[_17],[_18],[_19],[_20],[_21],[_22],[_23],[_24],[_25],[_26],[_27],[_28],[_29],[_30],[_31],[_32],[_33],[_34],[_35],[_36],[_37],[_38],[_39],[_40],[_41],[_42],[_43],[_44],[_45],[_46],[_47],[_48],[_49],[_50],[_51],[_52],[_53],[_54],[_55],[_56],[_57],[_58],[_59],[_60],[_61],[_62],[_63],[_64],[_65],[_66],[_67],[_68],[_69],[_70],[_71],[_72],[_73],[_74],[_75],[_76],[_77],[_78],[_79],[_80],[_81],[_82],[_83],[_84],[_85],[_86],[_87],[_88],[_89],[_90],[_91],[_92],[_93],[_94],[_95],[_96],[_97],[_98],[_99],[_100],[_101],[_102],[_103],[_104],[_105],[_106],[_107],[_108],[_109],[_110],[_111],[_112],[_113],[_114],[_115],[_116],[_117],[_118],
LET(
tokensArray,
FLATARRAY(
_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101, _102, _103, _104, _105, _106, _107, _108, _109, _110, _111, _112, _113, _114, _115, _116, _117, _118
),
escapedResult,
_ReplaceRecursive(
mask,
tokensArray,
1,
ROWS(tokensArray)
),
SUBSTITUTE(escapedResult,"\}","}")
)
)
如果
Array1
定义为:
=CHOOSE(SEQUENCE(number_of_args), arg_1, arg_2, arg_3, ..., arg_n))
其中
number_of_args
使得 number_of_args >= n
,那么您想要的结果是通过以下方式得出的:
=INDEX(Array1,SEQUENCE(SUM(1-ISERR(Arry1))))