zoukankan      html  css  js  c++  java
  • 根据计算公式求值

     

     计算公式的函数:

        /**
         * @desc 根据公式获取code
         *   1.code都需要加"[]"例如[a-1]+[b]+[c]就会返回["a-1",b,c];
         *   2.不加[]会自行忽略
         * @param {string} str 公式字符串
         * @return {array} _arr code组成的数组
         */
        function formulaToCode(str){
            var _arr=[];
            if(!str){return _arr}
            _arr=str.match(/[.+?]/g).join('').replace(/]/g,'').split(/[/);
            _arr.shift();
            return _arr;
        }
        /**
         * @desc 把请求到的单个code分散数据重新组合成按照公式的数据。
         * @desc 这个方法对应的要求说明:
         *          1.没有计算公式的code不能含有[]字符
         *          2.接口数据不能只有sname和data两个字段
         *          3.code只能是字母或下划线(_)开头的字母、数字和下划线组成的字符串(即:符合javascript变量命名要求)后改成了没有限制(-)也行
         *          4.不同设备不能使用相同的公式
         * @param {Object} obj 用 “公式:设备对象”组成的对象。
         * @param {Array} res 请求回来的数据数组对象,如:res.jsonList
         * @param {Array} other 根据请求回来的数据对象里面的键确定默认是【sname,data】,如果对象中还有其他的键需要加上,否则计算错误,因为是根据对象中每一个键都不同的时候来累加计算data的值
         * @return {Array} resArr 数据数组对象
         */
        function evalFormulaToRes(obj,res,other){
            other=other===undefined?['sname','data']:other;
            var resArr=[];//用于存放返回的数据对象
            if(res.length==0){return resArr;}//没有数据
            //1.解析res数组生成_tempO和_tempA
            for(var i=0,_tempO={},_tempA={};i<res.length;i++){
                if(_tempO[res[i].sname]===undefined){
                    _tempO[res[i].sname]={};
                    _tempA[res[i].sname]=[];
                }
                var keys='';
                for(var k in res[i]){
                    if(other.indexOf(k)===-1){
                        keys+=''+res[i][k];
                    }
                }
                if(keys===''){keys='tempIndex'+i}
                _tempO[res[i].sname][keys]=res[i];
                _tempA[res[i].sname].push(res[i]);
            }
            //2.外层循环每个公式
            for(var k in obj){
                if(k.split(/[[+-*/]/g).length<3){//2.1.如果公式是单个code,不存在运算直接concat进resArr
                    var key=k.replace(/[|]/g,'');
                    if(_tempA[k]!==undefined){
                        resArr=resArr.concat(_tempA[k]);
                    }else if(_tempA[key]!==undefined){
                        resArr=resArr.concat(_tempA[key]);
                    }
                }else{//2.2.公式存在运算
                    //2.2.1.取出每个code
                    var _arr=formulaToCode(k);
                    //2.2.2.根据每个code找出数据对象,把找到的数据对象的所有属性tempResArr
                    if(_arr.length>0){
                        for(var i=0,tempResArr={},len=0;i<_arr.length;i++){
                            if(_tempO[_arr[i]]!==undefined){
                                for(var n in _tempO[_arr[i]]){
                                    tempResArr[n]=_tempO[_arr[i]][n];
                                }
                            }
                        }
                    }
                    //2.2.3.循环tempResArr找出里面,每个属性生成变量
                    for(var ks in tempResArr){
                        var to=JSON.parse(JSON.stringify(tempResArr[ks]))
                        to.sname=k;to.data=formulaToData(_arr,_tempO,k,ks);
                        if(isNaN(to.data)||to.data==Infinity||to.data==-Infinity){
                            console.error('错误:"'+k+'"数据除以0');
                            to.data=0;
                        }
                        resArr.push(to);
                    }
                }
            }
            return resArr;
        }
        /**
         * @desc 将公式转换为数据
         * @param {*} _arr 
         * @param {*} _tempO 
         * @param {*} k 
         * @param {*} ks 
         */
        function formulaToData(_arr,_tempO,k,ks){
    //        var o={};
            for(var i=0;i<_arr.length;i++){
                var _str='';
                var r= new RegExp('\['+_arr[i]+'\]',"g");
                if(_tempO[_arr[i]]===undefined){//没有code
    //                _str='var _'+_arr[i]+'_='+0;
                    k=k.replace(r,0);
                }else{
                    var _to=_tempO[_arr[i]][ks];//有code没有某个属性
                    if(_to===undefined){
    //                    _str='var _'+_arr[i]+'_='+0;
                        k=k.replace(r,0);
                    }else{
    //                    _str='var _'+_arr[i]+'_='+_to.data;
                        k=k.replace(r,_to.data);
                    }
                }
    //            eval(_str);
            }
            return eval('('+k+')')+'';
        }

    特别说明:

    other 根据请求回来的数据对象里面的键确定默认是【sname,data】,如果对象中还有其他的键需要加上,否则计算错误,因为是根据对象中每一个键都不同的时候来累加计算data的值

    像这种就需再加上字段e,因为e有可能相同,如果相同,就会将data的值累加,导致计算的值的个数多与正确值

    使用举例:

        var obj={
            "[a-r]*2+[b]+[c]":""
        }
        var list=[
            {sname:"a-r",time:'01',data:1,date:'2019-01-02'},
            {sname:"b",time:'01',data:1,date:'2019-01-02'},
            {sname:"c",time:'01',data:1,date:'2019-01-02'},
            {sname:"a-r",time:'02',data:2,date:'2019-01-02'},
            {sname:"b",time:'02',data:2,date:'2019-01-02'},
            {sname:"c",time:'02',data:2,date:'2019-01-02'},
        ]
        console.log(evalFormulaToRes(obj,list));
        /*
        [
            {sname: "[a-r]*2+[b]+[c]", time: "01", data: "4", date: "2019-01-02"},
            {sname: "[a-r]*2+[b]+[c]", time: "02", data: "8", date: "2019-01-02"}
        ]
        */
     
     
  • 相关阅读:
    写了一个html5音乐播放器
    跨站脚本攻击之反射型XSS漏洞
    org.hibernate.ObjectNotFoundException异常一则
    addEventListener第二个参数的handleEvent
    IE的fireEvent方法
    DexMongoDB索引优化工具
    javascript 位运算符
    javascript contains方法来判断元素包含关系
    将uglifyjs添加到鼠标右键菜单
    过滤XSS(跨站脚本攻击)的函数和防止svn版本库被浏览
  • 原文地址:https://www.cnblogs.com/pengfei25/p/10300315.html
Copyright © 2011-2022 走看看