表驱动法 -优化逻辑分支

表驱动法 -优化逻辑分支

定义

表驱动法(Table-Driven Approach)是一种编程模式,可以将输入变量作为直接或间接索引在表里查找所需的结果或处理函数,而不使用逻辑语句(if-else 和 switch-case)。索引表可以是一个数组、map、或者其它数据结构。

事实上,凡是能通过逻辑语句来选择的事物,都可以通过查表来选择。对简单的情况而言,使用逻辑语句更为容易和直白,但随着逻辑链的越来越复杂,查表法也就愈发显得更具有吸引力。

使用总则

适当的情况下,采用表驱动法,所生成的代码会比复杂的逻辑代码更简单,更容易修改,而且效率更高。

应用

查询方式

可以分为:直接访问、索引访问、阶梯访问三种

直接访问

举例:查询今天是星期几?

常规写法:

const day = new Date().getDay()
let day_zh;
if(day === 0){day_zh = '星期日'
}else if(day === 1) {day_zh = '星期一'
}
...
else{day_zh = '星期六'
}// 或者 用 switch case
switch(day) {case 0:day_zh = '星期日'break;case 1:day_zh = '星期一'break;...
}

优化写法:将数据存到查询表里

const week = ['星期日', '星期一',..., '星期六']
const day = new Date().getDay(
const day_zh = week[day]

举例2:保险费率的查询,费率会根据年龄、性别、婚姻状态等不同情况变化

常规写法:使用逻辑分支(if 或 switch) 会非常麻烦

if (gender === 'female') {if (hasMarried) {if (age < 18) {//} else {// }} else if (age < 18) {//} else {// }
} else {...
}

优化写法:结构清晰,容易维护

enum ages {unAdult = 0,adult = 1
}
enum genders {female = 0,male = 1
}
enum marry = {unmarried = 0,married = 1
}const age2key = (age: number): string => {if (age < 18) {return ages.unAdult}return ages.adult
}// 查询表
const rates: number[] = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]// 通过检查条件,获取索引值
const premiumRate = {0: [age.unAdult, genders.female, marry.unmarried],1: [age.unAdult, genders.female, marry.married],2: [age.unAdult, genders.male, marry.unmarried],3: [age.unAdult, genders.male, marry.unmarried],4: [age.adult, genders.female, marry.unmarried],5: [age.adult, genders.female, marry.married],6: [age.adult, genders.male, marry.unmarried],7: [age.adult, genders.male, marry.unmarried]
}
type BoolCode = 0 | 1
const getRate = (age: number, hasMarried: BoolCode, gender: BoolCode) => {const ageKey: BoolCode = age2key(age)let index: string = ''Object.keys(premiumRate).forEach((key, i) => {const condition: BoolCode[] = premiumRate[key]if (condition[0] === ageKey && condition[1] === gender&& condition[2] === hasMarried) {index = key;}})return rates[index];
}
索引访问

在处理类似年龄范围的时候,无法通过简单的数学运算得到key,可以通过构建索引表、查询表来解决。
在这里插入图片描述

举例:

保险费率根据不同年龄费率不同,不满18岁费率0.2,18-65岁费率0.4,65岁及以上费率0.6。

假设人刚出生是0岁,最多能活到100岁,需要创建一个长度为101的数组,数组的下标对应着人的年龄,这样在0-17的每个年龄储存’<18’,在18-65储存’18-65’, 在65以上储存’>65’。

通过年龄就可以拿到对应的索引,再通过索引来查询对应的数据。

看起来这种方法要比上面的直接访问表更复杂,但是在一些很难通过转换键值、数据占用空间很大的场景下可以试试通过索引来访问。

const ages: string[] = ['<18', '<18', '<18', '<18', ... , '18-65', '18-65', '18-65', '18-65', ... , '>65', '>65', '>65', '>65']
const ageKey: string = ages[age];

索引访问优点

  1. 节省空间,比直接索引的全表法节约空间

  2. 灵活, 根据不同的字段生成不同的索引表

  3. 可维护性强

阶梯访问

不如索引结构直接,但是要比索引访问方法节省空间。

阶梯结构的基本思想:表中的记录对于不同数据范围有效,而不是对不同的数据点有效。
在这里插入图片描述

举例:考试按照分数进行等级评定

优 >= 90

良 < 90

中 < 80

差 < 60

常规写法

let level = '优'
if(score <60 ){level = '差'
}else if(score < 80) {level = '中'
}else if(score < 90) {level = '良'
}

优化写法

const levelTable = ['差', '中', '良', '优']
const scoreCeilTable = [60, 80, 90, 100]function getLevel(score) {const len = scoreCeilTable.lengthfor(let i = 0; i < len; i++) {const scoreCeil = scoreCeilTable[i]if(score <= scoreCeil) {return levelTable[i]}}return levelTable[len - 1]
}

注意事项:

  1. 留心边界端点

    注意边界:< 与 <=,确认循环能够在找出最高一级区间后恰当地终止。

  2. 二分查找替代顺序查找

    上面例子用了顺序查找,当数据比较大时,查找成本还是比较大的,应该考虑用二分查

  3. 考虑用索引访问来取代阶梯技术

    阶梯查找比较耗时,如果速度非常重要,可以用索引访问来取代阶梯,用空间换时间,但也要分情况,因为离散空间是不能够完全替代连续空间的

存储类型

查询表从存储上可以分为数据表、逻辑表。

  • 数据表:仅存储结果数据

  • 逻辑表:逻辑处理的代码或者引用

逻辑表

举例:

常规写法:

if (key = "Key A")
{执行 Key A 相关的行为。
}
else if (key = "Key B")
{执行 Key B 相关的行为。
}

优化写法

let table = {A: {data: "数据1",action () {console.log('action 1')}},B: {data: "数据2",action () {console.log('action 2')}}
}function handleTable(key) {return table[key]
}console.log(handleTable('A').data)
handleTable('A').action()

总结

表驱动的意义是将数据和逻辑剥离,在开发中,直接修改配置比修改逻辑要更加安全。数据的添加、删除比逻辑条件的添加、删除风险更低,数据来源也更加灵活。

在大多数情况下,优先使用直接访问和索引访问,除非两者实在无法处理,才考虑使用阶梯访问。

使用表的关键在于如何构建查询表内容,如何从表中查询,如何选择合适的查询表。

参考资料

一文道尽“表驱动法”

使用表驱动写出更优雅的条件判断

十分钟魔法练习:表驱动编程

使用表驱动法替代普通的判断分支语句(JS的深入探索)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/858395.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VMware与windows的共享文件夹没找到怎么办?

如果这样子添加&#xff0c;在ubuntu中还是没能找到。开机后有的时候仍然未发现共享文件夹。 二、解决办法 使用如下指令&#xff1a; sudo mount -t fuse.vmhgfs-fuse .host:/ /mnt/hgfs -o allow_other /mnt/hgfs/ 是挂载点&#xff0c;也可以指定其它挂载点 -o allow_other…

DHCP原理1-单个局域网出现多个DHCP服务器会发生什么

1. 背景 DHCP全称是Dynamic Host Configuration Protocol。其协议标准是RFC1541&#xff08;已被RFC2131取代&#xff09;&#xff0c;主要实现服务器向客户端动态分配IP地址&#xff08;如IP地址、子网掩码、网关、DNS&#xff09;和配置信息。其系统架构是标准的C/S架构。RFC…

自学SAP是学习ECC版本还是S4版本?

很多人想学SAP&#xff0c;问我应该学ECC版本还是S4版本&#xff0c;我的建议如果你是自学的话&#xff0c;我个人建议使用ECC版本就行&#xff0c;因为这两个版本前台业务和后台配置的操作差异并不大&#xff0c;主要差异在于数据库的差异&#xff0c;前台业务操作和后台系统配…

OS复习笔记ch12-1

文件系统 概述 文件是大多数应用程序的核心要素&#xff0c;文件系统是操作系统对用户来说最重要的部分之一。 本章的主要内容见下图&#xff1a; 文件&#xff0c;大家耳熟能详的就是的docx、pdf、jpg、MP4等各种后缀文件&#xff0c;根据任务需要文件又分成了文本、图片、…

构建可维护的返利系统:最佳实践与常见问题

构建可维护的返利系统&#xff1a;最佳实践与常见问题 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 在当今竞争激烈的电商市场中&#xff0c;返利系统作为一…

mediasoup源码分析(七)transport传输

transport传输 一、Tansport 转发到Producer二、RtpStreamRecv 处理收到的包三、数据传输到Router&#xff0c;再分发到Consumertips 一、Tansport 转发到Producer Transport收到数据packet后&#xff0c;会解析出packet中所带的ssrc字段&#xff0c;然后基于ssrc找到该数据的…

超越YOLOv8,飞桨推出精度最高的实时检测器RT-DETR!

众所周知&#xff0c;实时目标检测( Real-Time Object Detection )一直由 YOLO 系列模型主导。 飞桨在去年 3 月份推出了高精度通用目标检测模型 PP-YOLOE &#xff0c;同年在 PP-YOLOE 的基础上提出了 PP-YOLOE 。后者在训练收敛速度、下游任务泛化能力以及高性能部署能力方面…

django使用uuid的坑,据说有外国公司已经为此损失了超1w刀

错误的代码 import uuid from django.db import models class MyModel(models.Model): id models.CharField(max_length32, primary_keyTrue, editableFalse, defaultstr(uuid.uuid4())) # 其他字段...上述代码错误的地方在于&#xff0c;defaultstr(uuid.uuid4())这部分…

我国目前常用的卫星影像星座有哪些(高分二号、高分七号、吉林一号、高景一号······)

​ 点击下方全系列课程学习 点击学习—>ArcGIS全系列实战视频教程——9个单一课程组合系列直播回放 点击学习——>遥感影像综合处理4大遥感软件ArcGISENVIErdaseCognition 中国目前的遥感卫星在数量、种类和应用领域上都取得了显著进展&#xff0c;覆盖了陆地、气象、海…

ViT:5 Knowledge Distillation

实时了解业内动态&#xff0c;论文是最好的桥梁&#xff0c;专栏精选论文重点解读热点论文&#xff0c;围绕着行业实践和工程量产。若在某个环节出现卡点&#xff0c;可以回到大模型必备腔调或者LLM背后的基础模型重新阅读。而最新科技&#xff08;Mamba,xLSTM,KAN&#xff09;…

第1章、数据库概览

1、数据管理的三个阶段&#xff08;利用计算机进行数据管理&#xff09; 人工管理阶段——>文件系统阶段——>数据库系统阶段 人工管理阶段的特点&#xff1a;①数据不能长期保存在计算机中、②数据与程序不具有独立性、③数据不共享。 文件系统阶段&#xff0c;文件系…

博弈论(Nim 游戏)

公平组合游戏ICG 若—个游戏满足: 由两名玩家交替行动;在游戏进程的任意时刻&#xff0c;可以执行的合法行动与轮到哪名玩家无关;不能行动的玩家判负; 则称该游戏为一个公平组合游戏。 NIM博弈属于公平组合游戏&#xff0c;但城建的棋类游戏&#xff0c;比如围棋&#xff0c;…

Java17 --- SpringSecurity之前后端分离处理

目录 一、实现前后端分离 1.1、导入pom依赖 1.2、认证成功处理 1.3、认证失败处理 1.4、用户注销处理 1.5、请求未认证处理 1.6、跨域处理 1.7、用户认证信息处理 1.8、会话并发处理 一、实现前后端分离 1.1、导入pom依赖 <dependency><groupId>co…

Zabbix 7.0 LTS新特征

Zabbix 7.0 LTS版本是基于GNU Affero通用公共许可证第3版&#xff08;AGPLv3&#xff09;发布的&#xff0c;7.0 LTS更新了许多新的功能&#xff0c;包含合成终端用户Web监控、Zabbix proxy高可用性和负载均衡、重大性能和可扩展性提升、原生多因子认证&#xff08;MFA&#xf…

【python】python股票量化交易策略分析可视化(源码+数据集+论文)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

计组_计算机概要与设计

2024.06.23~2024.06.27&#xff1a;计算机组成原理学习笔记 CH1 计算机概要与设计 1.1 计算机的分类1.1.1 传统按照应用分类1.1.2 后PC时代1.1.3 存储容量 1.2 八大伟大设计思想1.2.1 两个设计原则1.2.2 四个提高性能1.2.3 存储器层次1.2.4 冗余提高可靠性 1.3 软硬件基础1.3.1…

React之useEffect

在React中&#xff0c;useEffect 是一个非常重要的Hook&#xff0c;它用于管理副作用操作。副作用指的是那些不直接与组件渲染相关的操作&#xff0c;例如数据获取、订阅、手动DOM操作等。本文将详细介绍 useEffect 的概念、基础使用、参数说明以及如何清除副作用&#xff0c;并…

软复位和硬复位

“硬复位”和“软复位”&#xff1a; 硬复位&#xff08;hard reset&#xff09;&#xff1a;通过外部复位引脚或者电源重启来实现的复位方式。 当硬复位信号有效时&#xff0c;系统会停止所有操作&#xff0c;并将所有寄存器和状态重置为初始状态。硬复位通常由硬件按钮或电…

【fastapi+mongodb】使用motor操作mongodb(三)

本篇文章介绍mongodb的删和改&#xff0c;下面是前两篇文章的链接&#xff1a; 【fastapimongodb】使用motor操作mongodb 【fastapimongodb】使用motor操作mongodb&#xff08;二&#xff09; delete delete 的用法基本和查找一致&#xff0c;包括delete_one&#xff08;删除…

借助AI快速提高英语听力:如何获得适合自己的听力材料?

英语听力是英语学习中的一个重要组成部分&#xff0c;它对于提高语言理解和交流能力至关重要。可理解性学习&#xff08;comprehensible input&#xff09;是语言习得理论中的一个概念&#xff0c;由语言学家Stephen Krashen提出&#xff0c;指的是学习者在理解语言输入的同时&…