文章

Google 表格公式 - 检索1

本文介绍使用 MAP 和 FILTER 代替 VLOOKUP

Google 表格公式 - 检索1

本文介绍使用 MAPFILTER 代替 VLOOKUP,不过在此之前,我们需要一些准备工作。

FILTER

FILTER 接受两个基本参数,第一个是过滤范围,第二个是过滤条件,第三个参数虽然名为“用于指明范围中的哪些行或列应该进行过滤”(官方文档),其实不就是另一个过滤条件么。而且第三个参数是可重复的,所以该函数其实可以拥有多于两个的过滤条件。

其实所谓的过滤条件,就是一组跟范围的列或行等长的布尔数组。限制是如果对范围进行行过滤,那么每一个条件都应该是长度跟范围行数相等的单列布尔数组,如果进行列过滤,同理。

简单的字符串相等,或者数字比较,可以使用形如 A1:A3=10B2:B6>15C2:C7="F" 这样的条件。复杂一点的可以用数组表达式。

如果条件的结果不是布尔数组,会被转换为布尔数组。比如如果是一堆由 0 和 1 组成的数组,其中 0 会变成 FALSE,1 会变成 TRUE

LAMBDA

跟编程语言中的一样,LAMBDA 是一个匿名函数。它接受至少一个参数,并使用参数定义一个表达式,调用该匿名函数时传入等量的参数就会返回表达式的计算结果。

比如 =LAMBDA(x, x*2)(10) 的结果是 20,=LAMBDA(x, y, (x+y)/2)(10, 20) 的结果是 15。

这里对于参数的命名有些要求:

  • 不能是数字,也不能以数字开头
  • 不能包含空格和特殊字符,可以包含下划线
  • 不能是列标识符,比如 A1,b2,val34 等(只要花足够多的时间,你会找到 VAL34 这个单元格的)

MAP

MAP 函数也同编程语言中的 map 函数差不多,可以对数组内的每一个值应用一个 lambda 表达式。对于有些不能使用 ARRAYFORMULA 进行扩展计算的函数(比如 SUMIFS),MAP 简直不要太强大!

例子这里就不举了,基础教程可以查看官方文档。这里主要说一下映射范围的一些细节。

一般来说,传递给 MAP 的要进行 lambda 计算的范围是一个单列或者单行。如果是一个单列,那么每一行的值进行 lambda 计算之后的结果只能是单行,不能是多行。同样,如果范围是一个单行,那么每一列的值进行 lambda 计算后的结果只能是单列,不能是多列。

比如以下样表,

 ABCD
1IDNameAgeSex
21Tom12M
32John43M
42Alice45F
53Dom23M
64Tina34F

这里 ID 列有两个 2,虽然实际情况通常不会这样,但为了实验效果,姑且这样设置。

正常的 MAP 映射,在 F2 处的公式为 =MAP(E2:E3, LAMBDA(x, FILTER(A2:D6, A2:A6=x)))

 EFGHI
1RangeIDNameAgeSex
211Tom12M
333Dom23M

但如果 Range 列中其中一个是 2 的话,就会变成这样,

 EFGHI
1RangeIDNameAgeSex
211Tom12M
32#VALUE!   

错误是 结果应为单行。

但是如果映射范围是一个单值,就没有这个情况了。

比如把 F2 处的公式换为 =MAP(E2, LAMBDA(x, FILTER(A2:D6, A2:A6=x)))

 EFGHI
1RangeIDNameAgeSex
222John43M
3 2Alice45F

但是这种用法几乎也没有吧。

VLOOKUP

之所以要讲上面的这种情况,是因为 VLOOKUP 在查找的时候,只会返回第一个匹配的行。

比如将 F2 的公式换为 =ARRAYFORMULA(VLOOKUP(E2, A2:D6, {1,2,3,4}, FALSE))

 EFGHI
1RangeIDNameAgeSex
222John43M
3     

其实 ARRAYFORMULAVLOOKUP 的组合也还可以了,主要有点别扭的地方是一方面 VLOOKUP 只能从范围里的第一列查找,另一方面是在指定要显示的列时是用数字指定的,这样当范围列发生变化时,数字不会跟着变化。因此就琢磨用 MAPFILTER 替换 ARRAYFORMULAVLOOKUP

替换

替换也很简单,把 F2 的公式换为 =MAP(E2:E3, LAMBDA(x, FILTER({B2:B6,D2:D6}, A2:A6=x)))

 EFG
1RangeNameSex
21TomM
33DomM

这样一来,通过 FILTER 的过滤条件确定查找列,就不用非得限定在范围的第一列了,通过 FILTER 的过滤范围可以自定义要显示的列,但这并不是通过数字指定的,而是通过范围指定的,因此哪怕有些列移动了,该公式也不会出错。(可以一定程度上自动矫正)

但是在性能方面,我没有测试。

本文由作者按照 CC BY 4.0 进行授权