递归 LAMBDA 以通过查找 table 中的特定替代品替换字符

Recursive LAMBDA to replace characters by specific substitutes from a lookup table

目标是遍历字符的行 table 并用它的替代字符替换每个字符。

这个例子中的字符table是={"&","&amp;";"<","&lt;";">","&gt;";"'","&apos;";"""","&quot;"},或者:

*(旁注:在这种情况下,"&","&amp;" 必须排在列表的最后,否则它将替换之前替换中的其他出现,因为我们是从最后到第。)

公式:

=LAMBDA(XML,Pos,
LET(
Cls,{"&","&amp;";"<","&lt;";">","&gt;";"'","&apos;";"""","&quot;"},
Row,IF(ISOMITTED(Pos),ROWS(Cls),Pos),
Crf,INDEX(Cls,Row,1),
Crr,INDEX(Cls,Row,2),
Sub,SUBSTITUTE(XML,Crf,Crr),
IF(Row=0,XML,ENCODEXML(Sub,Row-1))
))

=ENCODEXML("sl < dk & jf") 的预期结果为 sl &lt; dk &amp jf
我收到 #VALUE! 错误。

  1. 你需要在递归上有一个出口:
=LAMBDA(XML,Pos,
LET(
Cls,{"&","&amp;";"<","&lt;";">","&gt;";"'","&apos;";"""","&quot;"},
Row,IF(ISOMITTED(Pos),ROWS(Cls),Pos),
Crf,INDEX(Cls,Row,1),
Crr,INDEX(Cls,Row,2),
Sub,SUBSTITUTE(XML,Crf,Crr),
IF(Row>1,ENCODEXML(Sub,Row-1),Sub)
))
  1. 您需要在调用中添加,
=ENCODEXML("sl < dk & jf",)

或者正如@Filcuk 发现的(我刚刚了解到)如果它是可选的,则需要使用 []

声明

即:

=LAMBDA(XML,[Pos],
LET(
Cls,{"&","&amp;";"<","&lt;";">","&gt;";"'","&apos;";"""","&quot;"},
Row,IF(ISOMITTED(Pos),ROWS(Cls),Pos),
Crf,INDEX(Cls,Row,1),
Crr,INDEX(Cls,Row,2),
Sub,SUBSTITUTE(XML,Crf,Crr),
IF(Row>1,ENCODEXML(Sub,Row-1),Sub)
))

那么,就不需要了:

=ENCODEXML("sl < dk & jf")

只是为了补充 Scott 上面的回答;通过名称管理器使用递归 lambda 似乎已经过时(如果没有明确需要命名函数供以后使用)。因为 REDUCE() 本身就是一个递归函数。因此,可以应用以下结构:

=LET(X,<LookupTable>,REDUCE(<InputValue>,INDEX(X,0,1),LAMBDA(a,b,SUBSTITUTE(a,b,VLOOKUP(b,X,<ReturnCol>,0)))))

其中:

  • <LookupTable> - 指的是最左边的列包含查找值的矩阵。对于 VLOOKUP() 尤其如此,但是,对于不同的结构,可以开始使用 XLOOKUP()(以使解决方案更适用);
  • <InputValue> - 对需要应用替换的输入字符串的引用;
  • <ReturnCol> - 除了第 1 点:当使用 VLOOKUP() 时,需要给出一个引用具有替换值的列的索引;

在 OP 给出的情况下,这将转换为:

=LET(X,{"&","&amp;";"<","&lt;";">","&gt;";"'","&apos;";"""","&quot;"},REDUCE("sl < dk & jf",INDEX(X,0,1),LAMBDA(a,b,SUBSTITUTE(a,b,VLOOKUP(b,X,2,0)))))