表驱动法 -优化逻辑分支

表驱动法 -优化逻辑分支

定义

表驱动法(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;根据任务需要文件又分成了文本、图片、…

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

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

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

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

ViT:5 Knowledge Distillation

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

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…

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

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

【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;指的是学习者在理解语言输入的同时&…

时空预测 | 基于深度学习的碳排放时空预测模型

时空预测 模型描述 数据收集和准备&#xff1a;收集与碳排放相关的数据&#xff0c;包括历史碳排放数据、气象数据、人口密度数据等。确保数据的质量和完整性&#xff0c;并进行必要的数据清洗和预处理。 特征工程&#xff1a;根据问题的需求和领域知识&#xff0c;对数据进行…

Canvas绘制图片和区域

如何使用Canvas在图片上绘制区域&#xff1f; 一. 首先&#xff0c;我们需要初始化三个canvas画布&#xff08;初始化Canvas&#xff09; initCanvas() {// 初始化canvas画布let canvasWrap document.getElementsByClassName("canvas-wrap");this.wrapWidth canva…

Android中如何动态的调整Dialog的背景深暗

本文首发于公众号“AntDream”&#xff0c;欢迎微信搜索“AntDream”或扫描文章底部二维码关注&#xff0c;和我一起每天进步一点点 在 Android 开发中&#xff0c;当你使用 Dialog 或 DialogFragment 时&#xff0c;可以通过设置 Window 的背景变暗来突出它的可见性。这个效果…

【密码学】分组密码

文章目录 分组密码的模式分组密码与流密码模式明文分组与密文分组 ECB模式ECB定义ECB特点对ECB模式的攻击改变分组顺序攻击 CBC模式CBC定义初始化向量IVCBC特点对CBC模式的攻击对初始向量进行反转攻击填充提示攻击 CFB模式CFB定义对CFB模式的攻击重放攻击 OFB模式OFB定义CFB模式…

【LocalAI】(13):LocalAI最新版本支持Stable diffusion 3,20亿参数图像更加细腻了,可以继续研究下

最新版本v2.17.1 https://github.com/mudler/LocalAI/releases Stable diffusion 3 You can use Stable diffusion 3 by installing the model in the gallery (stable-diffusion-3-medium) or by placing this YAML file in the model folder: Stable Diffusion 3 Medium 正…

PriorityQueue详解(含动画演示)

目录 PriorityQueue详解1、PriorityQueue简介2、PriorityQueue继承体系3、PriorityQueue数据结构PriorityQueue类属性注释完全二叉树、大顶堆、小顶堆的概念☆PriorityQueue是如何利用数组存储小顶堆的&#xff1f;☆利用数组存储完全二叉树的好处&#xff1f; 4、PriorityQueu…

React AntDesign Layout组件布局刷新页面错乱闪动

大家最近在使用React AntDesign Layout组件布局后刷新页面时&#xff0c;页面布局错乱闪动 经过组件属性的研究才发现&#xff0c;设置 hasSider 为 true 就能解决上面的问题&#xff0c;耽搁了半天的时间&#xff0c;接着踩坑接着加油&#xff01;&#xff01;&#xff01; …

pytorch实现的面部表情识别

一、绪论 1.1 研究背景 面部表情识别 (Facial Expression Recognition ) 在日常工作和生活中&#xff0c;人们情感的表达方式主要有&#xff1a;语言、声音、肢体行为&#xff08;如手势&#xff09;、以及面部表情等。在这些行为方式中&#xff0c;面部表情所携带的表达人类…

SQL找出所有员工当前薪水salary情况

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 描述 有一个薪水表…