Google 表格公式 - 检索1
本文介绍使用 MAP 和 FILTER 代替 VLOOKUP
本文介绍使用 MAP
和 FILTER
代替 VLOOKUP
,不过在此之前,我们需要一些准备工作。
FILTER
FILTER
接受两个基本参数,第一个是过滤范围,第二个是过滤条件,第三个参数虽然名为“用于指明范围中的哪些行或列应该进行过滤”(官方文档),其实不就是另一个过滤条件么。而且第三个参数是可重复的,所以该函数其实可以拥有多于两个的过滤条件。
其实所谓的过滤条件,就是一组跟范围的列或行等长的布尔数组。限制是如果对范围进行行过滤,那么每一个条件都应该是长度跟范围行数相等的单列布尔数组,如果进行列过滤,同理。
简单的字符串相等,或者数字比较,可以使用形如 A1:A3=10
,B2:B6>15
,C2: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 计算后的结果只能是单列,不能是多列。
比如以下样表,
A | B | C | D | |
---|---|---|---|---|
1 | ID | Name | Age | Sex |
2 | 1 | Tom | 12 | M |
3 | 2 | John | 43 | M |
4 | 2 | Alice | 45 | F |
5 | 3 | Dom | 23 | M |
6 | 4 | Tina | 34 | F |
这里 ID 列有两个 2,虽然实际情况通常不会这样,但为了实验效果,姑且这样设置。
正常的 MAP
映射,在 F2
处的公式为 =MAP(E2:E3, LAMBDA(x, FILTER(A2:D6, A2:A6=x)))
,
E | F | G | H | I | |
---|---|---|---|---|---|
1 | Range | ID | Name | Age | Sex |
2 | 1 | 1 | Tom | 12 | M |
3 | 3 | 3 | Dom | 23 | M |
但如果 Range
列中其中一个是 2 的话,就会变成这样,
E | F | G | H | I | |
---|---|---|---|---|---|
1 | Range | ID | Name | Age | Sex |
2 | 1 | 1 | Tom | 12 | M |
3 | 2 | #VALUE! |
错误是 结果应为单行。
。
但是如果映射范围是一个单值,就没有这个情况了。
比如把 F2
处的公式换为 =MAP(E2, LAMBDA(x, FILTER(A2:D6, A2:A6=x)))
,
E | F | G | H | I | |
---|---|---|---|---|---|
1 | Range | ID | Name | Age | Sex |
2 | 2 | 2 | John | 43 | M |
3 | 2 | Alice | 45 | F |
但是这种用法几乎也没有吧。
VLOOKUP
之所以要讲上面的这种情况,是因为 VLOOKUP
在查找的时候,只会返回第一个匹配的行。
比如将 F2
的公式换为 =ARRAYFORMULA(VLOOKUP(E2, A2:D6, {1,2,3,4}, FALSE))
,
E | F | G | H | I | |
---|---|---|---|---|---|
1 | Range | ID | Name | Age | Sex |
2 | 2 | 2 | John | 43 | M |
3 |
其实 ARRAYFORMULA
加 VLOOKUP
的组合也还可以了,主要有点别扭的地方是一方面 VLOOKUP
只能从范围里的第一列查找,另一方面是在指定要显示的列时是用数字指定的,这样当范围列发生变化时,数字不会跟着变化。因此就琢磨用 MAP
加 FILTER
替换 ARRAYFORMULA
加 VLOOKUP
。
替换
替换也很简单,把 F2
的公式换为 =MAP(E2:E3, LAMBDA(x, FILTER({B2:B6,D2:D6}, A2:A6=x)))
,
E | F | G | |
---|---|---|---|
1 | Range | Name | Sex |
2 | 1 | Tom | M |
3 | 3 | Dom | M |
这样一来,通过 FILTER
的过滤条件确定查找列,就不用非得限定在范围的第一列了,通过 FILTER
的过滤范围可以自定义要显示的列,但这并不是通过数字指定的,而是通过范围指定的,因此哪怕有些列移动了,该公式也不会出错。(可以一定程度上自动矫正)
但是在性能方面,我没有测试。