今天拿到一个需求,需要将'20+15.3+{a}/{b}-2*3.0'后台传过来的字符串进行运算并拿到最终值,其中还可以传变量,也允许浮点数的存在,在参考了中国的流浪猫<js方------将字符串转换成算术表达式,并计算出结果,例如(‘92-4*5/3‘)>https://blog.csdn.net/weixin_46611729/article/details/121293766与Hason_Huang<js 实现String.format()>https://blog.csdn.net/a258831020/article/details/46988887之后实现了需求,其中主要增加的是对浮点数部分的处理,代码如下
String.prototype.format = function(args) { var result = this; if (arguments.length > 0) { if (arguments.length == 1 && typeof(args) == "object") { for (var key in args) { if (args[key] != undefined) { var reg = new RegExp("({" + key + "})", "g"); result = result.replace(reg, args[key]); } } } else { for (var i = 0; i < arguments.length; i++) { if (arguments[i] != undefined) { //var reg = new RegExp("({[" + i + "]})", "g");//这个在索引大于9时会有问题 var reg = new RegExp("({)" + i + "(})", "g"); result = result.replace(reg, arguments[i]); } } } } return result; } const isNumber = (val) => { const regPos = /^\d+(\.\d+)?$/ // 非负浮点数 const regNeg = /^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$/ // 负浮点数 if (regPos.test(val) || regNeg.test(val)) { return true } else { return false } } function getDecimals(arr) { const index = arr.indexOf('.') // 找到第一个小数点 // 找到之后拿出前面的 if (index != -1) { let arr1 = arr.slice(0, index) let arr2 = arr.slice(index + 1) // 将前面那一部分倒叙,然后拿出截止到计算符号之前的东西 arr1 = arr1.reverse() let number1 = [] let number2 = [] let len1 = 0 let len2 = 0 for (let item of arr1) { if (isNumber(item)) { number1.push(item) len1 += 1 } else { break } } // 直接操作后面那一部分的 for (let item of arr2) { if (isNumber(item)) { number2.push(item) len2 += 1 } else { break } } number1 = number1.reverse() // 将number1中的元素和number中的元素以及小数点拼接起来就是那个小数 let arr3 = [...number1, '.', ...number2] let number3 = '' arr3.map(item => { number3 = number3 + `${item}` }) arr.splice(index - len1, index + len2 - 1, Number(number3)) return getDecimals(arr) } else { return arr } } function sumResutl(arr) { // 如果数组元素中有乘除加减运算符 const i1 = arr.indexOf('*') const i2 = arr.indexOf('/') const i3 = arr.indexOf('-') const i4 = arr.indexOf('+') if (i1 !== -1) { // 拿到*运算符前面数字的索引 const index = i1 - 1 // 计算出结果 const result = arr[index] * arr[i1 + 1] // 修改数组元素 arr.splice(index, 3, result) // 如果剩下的元素不只一位,则继续调用函数自身 if (arr.length > 1) { sumResutl(arr) } } else if (i2 !== -1) { // 拿到/运算符前面数字的索引 const index = i2 - 1 // 计算出结果 const result = arr[index] / arr[i2 + 1] // 修改数组元素 arr.splice(index, 3, result) // 如果剩下的元素不只一位,则继续调用函数自身 if (arr.length > 1) { sumResutl(arr) } } else if (i3 !== -1) { // 拿到-运算符前面数字的索引 const index = i3 - 1 // 计算出结果 const result = arr[index] - arr[i3 + 1] // 修改数组元素 arr.splice(index, 3, result) // 如果剩下的元素不只一位,则继续调用函数自身 if (arr.length > 1) { sumResutl(arr) } } else if (i4 !== -1) { // 拿到+运算符前面数字的索引 const index = i4 - 1 // 计算出结果 const result = arr[index] + arr[i4 + 1] // 修改数组元素 arr.splice(index, 3, result) // 如果剩下的元素不只一位,则继续调用函数自身 if (arr.length > 1) { sumResutl(arr) } } return arr[0] } function compute(str, arges) { let data = str.format(arges) // 拿到结果之后开始处理为运算 const arr = data.split('') // 准备一个容器 let newArray = [] // 遍历字符串数组 arr.forEach((item, i) => { // 如果当前字符串是数字 if (isNumber(item)) { // 拿到最后一个数组元素 let endStr = newArray[newArray.length - 1] // 拿到最后一个数组元素的索引 const endIndex = newArray.length - 1 // 判断最后一个数组元素是否是数字 if (isNumber(endStr)) { // 如果最后一个数组元素是数字,则进行拼接 endStr += item // 修改最后一个数组元素 newArray.splice(endIndex, 1, endStr) } else { // 如果最后一个数组元素是运算符,则将当前项直接添加到数组 newArray.push(item) } } else { // 如果当前项是运算符,则将当前项直接添加到数组 newArray.push(item) } }) // 将数字与运算符遍历,将字符串类型的数字转换成数字类型 newArray = newArray.map((item) => (isNumber(item) ? parseFloat(item) : item)) // 合并一下小数点 let newData = getDecimals(newArray) let num = sumResutl(newData) return num } // 引用案例 // 先在需要用的地方引入compute函数 // let template = '20+15.3+{a}/{b}-2*3.0' // 调用函数 // console.log(compute(template,{a:2,b:1}))