Excel常用公式之LOOKUP

简介

LOOKUP公式用于通过查询值从一个表中查找想要的对应值。例如利用学生的名字从成绩单中查找他对应的分数。

常规用法

LOOKUP(查询值,查询列表,返回列表)
在这里插入图片描述
如图所示AB两列为省份和其对应的代码。在E2位置的公式为=LOOKUP(D2,B2:B33,A2:A33),意思是在B列中查找和D2相同的值,如果找到了就返回对应的A列的值。在H2位置的公式为=LOOKUP(G2,A2:A33,B2:B33),意思是在A列中查询G2的值,如果找到了就返回对应的B列的值。

从结果可以看出,这两个查询都失败了,一个返回了错误的结果,一个不返回结果。这是因为Lookup函数的设计十分搞糟,一度导致没人愿意用这个函数,直到有人开发出高级用法。那么这个函数糟糕在哪呢?

在LOOKUP函数中,查询列表必须按从小到大的顺序排列,那有人说这里B列是字符串怎么从小到大,实际上字符串也是有大小的,字符串的大小就是字符在编码表中的编号,从第一个字符开始依次比较,直到比出大小。为什么微软的程序员要做这么糟糕的设计呢?我的理解是为了提高搜索效率,据我猜测,他们应该采用的是二分查找的策略,在二分查找过程中,返回不大于查询值的最后一个被比较大小的值。

二分查找具体可以看下面这篇文章,有一个比较好理解的动态图:二分查找(Binary Search)

但这就导致这个函数几乎没法使用了,毕竟大部分时候查询列表都是乱序的。最终这个函数的结果很迷,想具体了解的可以看下面的补充说明。

那么为什么H2也查不到结果呢?明明A列已经按从小到大的顺序排列了。这是因为G列是数字,而A列是文本,想要查询就把G列转为文本吧。把H2的公式改为=LOOKUP(TEXT(G2,0),A2:A33,B2:B33)即可,结果如下:
在这里插入图片描述

补充说明

如果你依旧无法理解LOOKUP函数为什么会返回错误的结果,可以看如下内容:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
通过三面的个实验结果,我基本可以确定LOOKUP这个函数就是采用的二分查找法。按照二分查找的原理,这个列表有6个数,那么图2对应步骤如下:

  1. 比较第3个数,发现是5,比查询值4更大,由于算法认为列表是从小到大排列的,因此后续只需要比较第1到第2个数就行。
  2. 比较第1个数,发现是1,比查询值4更小,那么算法认为正确的值就是第2个数,于是返回B列对应行的“反”。

图3对应的步骤如下:

  1. 比较第3个数,发现是5,比查询值4更大,由于算法认为列表是从小到大排列的,因此后续只需要比较第1到第2个数就行。
  2. 比较第1个数,发现是5,比查询值4更大,由于第1个数前面已经没有数字了,因此认为找不到结果,返回错误。

掌握LOOKUP函数的原理之后,我们就可以调戏一下它,看下面的例子,你能想清楚为什么会出现这样的结果吗?明明有3个正确答案,LOOKUP竟然全都错过了!
在这里插入图片描述
答案如下:

  1. 比较第3个数,发现是3,比查询值4更小,由于算法认为列表是从小到大排列的,因此后续只需要比较第4到第6个数就行。
  2. 比较第5个数,发现是3,比查询值4更小,因此后续只需比较第6个数。
  3. 发现第6个数是5,比4大,按照算法设定,只返回比查询值小的最后一个被比较大小的值,因此退回一步,返回第5个数对应的B列,也就是“设”。

我们再来看一个有趣的例子,如果所有答案都是正确答案会怎么样?

在这里插入图片描述
这里我们发现了LOOKUP函数的另一个特性,就是将正确结果当作比查询值小来对待,会继续向后查找直到最后一个符合要求的值。这大概是为了保证算法的一致性,看来微软还是动了点脑子。如果不这么做,那么列表长度不同,二分查找时二分的位置不同,都会导致不同的结果,毕竟每个值都是正确结果嘛,那我二分时第一个比较的值不就成了返回值了嘛,这会造成混乱,所以不如每次都返回最后一个。

具体查找步骤如下:

  1. 比较第3个数,发现是4,当作比查询值4更小,由于算法认为列表是从小到大排列的,因此后续只需要比较第4到第6个数就行。
  2. 比较第5个数,发现是4,当作比查询值4更小,因此后续只需比较第6个数。
  3. 发现第6个数是4,当作比查询值4更小,由于已经是最后一行了,按照算法设定,只返回比查询值小的最后一个被比较大小的值,因此返回第6个数对应的B列,也就是“计”。

高级用法

Lookup(1,0/(查询条件),返回列表)

上面已经提到了,LOOKUP函数的常规用法几乎毫无用处,但是有人开发了它的高级用法后,这个函数就成了最强查询函数,吊打VLOOKUP函数毫无问题。

首先介绍一下这个高级用法,查询条件是一个和返回列表维度相同的True/False列表。在计算机中,True=1,False=0。那么如果查询条件为False的时候,分母为0,那么计算结果就是错误的。而如果查询条件为True,那么计算结果为0。然后重点来了,LOOKUP这个函数在查询时,如果查询列表的值为错误,那么会跳过,这里0/(查询条件)的计算结果不就是查询列表吗。这个查询列表里为False的值计算结果都是错误,全都会跳过,最后只剩下为True的项目。查询值为“1”,按照LOOKUP函数的尿性,它会返回不大于“1”的最后一个被比较的值,也就是这里唯一为True的值,当然,你把“1”改成其他大于等于“0”的数字也可以,随你喜欢,结果如下图所示。可以看出,这次终于得到了正确的结果。

在这里插入图片描述
为什么说这个LOOKUP函数是最强查询函数呢?因为这里的“查询条件”可以是任意的逻辑判断语句,不仅仅限于等于判断。比如这里我们改一下,我想查询“上海”对应的编码怎么办,少了个“市”那么正常情况下就查不到相等的值啊。简单,用SEARCH函数啊,SEARCH函数返回的是查询字符串在被查询字符串中首次出现的位置编号,如果查不到则返回出错。因此只要能查到值分母就不为零,那么0/(查询条件)就不出错,不出错的结果即是最终查询到的结果。

在这里插入图片描述

补充说明

如果你无法理解上面的内容,那么请看下面的补充说明。
在这里插入图片描述
我们先看看0/(查询条件)的结果是什么,如上图所示,只有第4行4=4的结果为True,其他几行结果都是False,而False相当于0,分母为0自然就报了一个#DIV/0!的错误,意思是“error:divided by 0!”。

然后我们再回顾一下我们的查询公式:
Lookup(1,0/(查询条件),返回列表)

其中0/(查询条件)列表只有第4个不报错,而报错的都被舍去了,也就是说最后参与和查询值比较的列表只有这一行的数据,只要查询值大于等于0/(查询条件)列表中这一行的值,那么就会返回返回列表中这一行对应的值。而0/True=0/1=0,所以只要查询值大于等于0不就可以了,反正你莫得选择,候选人就这一个,你爱选不选。

在这里插入图片描述
如上面的例子所示,我们用上了高级用法,这里我们将查询值设为0是为了更好说明问题,建议大家还是用1保险,以防哪天微软突然良心发现了修改代码。

由于0/(查询条件)列表中有三行为0,三行为错误,错误的行会被删掉,那么问题相当于转化为如下图所示:
在这里插入图片描述
上图的结果我相信大家都知道是怎么来的吧?3个都对选最后一个而已。

发布了22 篇原创文章 · 获赞 21 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/liucc09/article/details/104759288
今日推荐