什么是表驱动法
所谓表驱动法(Table-Driven Approach),简单讲是指用查表的方法获取值。 我们平时查字典以及念初中时查《数学用表》找立方根就是典型的表驱动法。在数值不多的时候我们可以用逻辑语句(if 或 switch case)的方法来获取值,但随着数值的增多逻辑语句就会越来越长,此时表驱动法的优势就显现出来了。
表驱动法的使用主要分为三种方式:直接访问表,索引访问表和阶梯访问表,下面分别举例说明一下这三种方法。
直接访问表
直接访问是最简单也是最常用的一种方法,查表本质其实就是去索引“键”来获得“值”,有点像获得数组值一样,给定下标index,然后 array[index] 就获得数组在相应下标处的数值。
举个我工作中的栗子:需要根据国家代码,确定国家的货币符号和国家的 icon 图标(这里国家代码和取值是确定且唯一的)。正常的时候我们可能会采用 if else,或者 switch case 的方式来处理这个问题,你可能会这样写这个函数(这里用 switch 来举例):
1 | function getCurrencyAndIcon (sid) { |
上面的写法其实也没有问题,也是常用的写法,但是这里不妨问一下,这里只是4个国家,但是假如是 200 个国家呢?你还是这样写? 那你的函数会有多长?是不是感觉不能忍?
现在我们采用表驱动法中的直接访问来实现这个函数:
1 | const array = [ // 创建一个对象数组 |
以上对比代码量上看起来可能感觉差的不是太多?实际上是差别还是很大的,尤其是当数据量大的时候,尤其是你如果用 if else 来写更是明显,因为篇幅问题,这里只举栗了4个数据,而且所有的配置只要修改 array 数组即可,不会像用 switch 和 if else 语句实现的时候增删改时需要改原函数代码。
这里可能大家会遇到,索引是不同的随机数字或者字符串之类的,这也没关系,把数组改成对象就行:
1 | const dataObj = { // 创建一个对象 |
索引访问表
对于索引访问表,它适用于这样的情况,假设你经营一家商店,有100种商品,每种商品都有一个 id 号,但很多商品的描述都差不多,所以 只有30条不同的描述,现在的问题是建立商品与商品描述的表,如何建立?还是同上面的直接访问表的做法来一一对应吗?那样描述会扩充到100的,会有70个描述是重复的!如何解决这个问题呢?方法是建立一个100长的索引,然后这些索引指向相应的描述,注意不同的索引可以指向相同的描述,这样就解决了表数据冗余的问题啦。
这里举例采用12个商品,每个商品对应一个 id 号,然后12个商品只有4个不同的描述来举例子处理一下这个问题:
假如你拿到这个需求,不采用表驱动法的情况下,你可能会直接用 switch case 或者 if else 来处理这个需求:
1 | // 这里假设id 1001 1002 1003 商品的描述相同,1004 1005 1010的描述相同 |
采用直接访问表的情况下,可能是这样的:
1 | // 这里假设id 1001 1002 1003 商品的描述相同,1004 1005 1010的描述相同 |
那如果采用索引访问表,会是怎么样的呢?
1 | // 这里假设id 1001 1002 1003 商品的描述相同,1004 1005 1010的描述相同 |
阶梯访问表
第三种表驱动法是阶梯访问表,它适用于数据不是一个固定的值,而是一个范围的问题,比如将百分制成绩转成五级分制(我们用的优、良、中、合格、不合格,西方用的 A、B、C、D 和F),假定转换关系是当成绩在 90-100 区间,判为A,成绩在 80-89 区间,判为B,成绩在 70-79 区间,判为 C,成 绩在 60-69 区间,判为D,成绩在 60 以下,判为 F。现在的问题是,怎么用表格对付这个范围问题?一种笨笨的方法直接用 if else 判断,还有是申请一个 100 长度的表,然后在这个表中填充相应的等级就行了,但这样太浪费空间了,有没有更好的方法?
先看看 if else 的实现方法:
1 | getLevel (grade) { |
这里就不在再示例直接访问表和索引访问表的实现方法拉,虽然也可以实现,实现,但是直接访问表和索引访问表在这里的需求上都太浪费空间。
阶梯访问表的实现法:
1 | const gradeArray = [59, 69, 79, 89, 100] |
这里童鞋们看到了结果,可能觉得代码量还是差不多,而且感觉阶梯访问表的方式逻辑都更负责了,还增加了遍历等增加时间复杂度的操作。
但是,这里的举例都是数据量小,假设第上面阶梯访问表的需求存在几百,几千个范围呢,你还是用 if else 的话会产生什么样的结果自然不必多说了吧?
以上就是表驱动法的总结,大家学会了么?快去改改项目中 if else 和 switch case 的代码先试试水吧,记住,数据量越大,表驱动法优势越大噢!