I want to process two objects.
obj1 array object having formulas.
obj2 having values. I want to process/calculate both objects to get result such that key present in obj1 becomes actual key in output and value get processed with formula. Did it with EVAL but don't want to use eval it.
Please suggest any other method to do the same.
const obj1 = [{ _id: '5 f467650890a7444d8d9ea5b', keyname: 'fTime',
PTag: '(FaultHrs*360)+(FaultMins*60)+FaultSecs', __v: 0 },
{ _id: '5 f467650890a7444d8d9ea5b', keyname: 'rTime',
PTag: '(RunHrs*360)+(RunMins*60)+RunSecs', __v: 0 }
]
const obj2 = { FaultHrs: 2, FaultMins: 0, FaultSecs: 49, RunHrs: 1, RunMins: 0, RunSecs: 0,}
const res = obj1.reduce((res, k) => {
// find out parameters in formula
const matches = k.PTag.match(/[a-zA-Z]+/g);
// substitute them with numbers
const newTag = matches.reduce((tag, m) => tag.replace(m, obj2[m] || 0), k.PTag);
// calculate result
res[k.keyname] = eval(newTag);
return res;
}, {});
console.log(res)
You can try to use New Function() construct, instead eval(). Change your code line
res[k.keyname] = eval(newTag);
Into
res[k.keyname] = (new Function(`return ${newTag};`))();
But under the hood it's same eval() actually. Or you could try to roll your own math expression parser, through abstract syntax trees, but there's plenty of them in internet already and besides there is no guarantee that your parser will be superior to integrated and time tested JS engine expression parser.
You could try using a module such as math.js, it includes an evaluate function which does not use eval under the hood (I believe an older version did).
There are still security risks, they are detailed in the math.js documentation math.js security, but they should be lower than using eval directly.
const obj1 = [{ _id: '5 f467650890a7444d8d9ea5b', keyname: 'fTime',
PTag: '(Fault_Hrs1*360)+(Fault_Mins1*60)+Fault_Secs1', __v: 0 },
{ _id: '5 f467650890a7444d8d9ea5b', keyname: 'rTime',
PTag: '(RunHrs*360)+(RunMins*60)+RunSecs', __v: 0 }
]
const obj2 = { Fault_Hrs1: 2, Fault_Mins1: 0, Fault_Secs1: 49, RunHrs: 1, RunMins: 0, RunSecs: 0,}
const res = obj1.reduce((res, k) => {
// find out parameters in formula
const matches = k.PTag.match(/([a-zA-Z]{1}[a-zA-Z0-9_]+)/g);
// substitute them with numbers
const newTag = matches.reduce((tag, m) => tag.replace(m, obj2[m] || 0), k.PTag);
// calculate result, using math.js evaluate function.
res[k.keyname] = math.evaluate(newTag);
return res;
}, {});
console.log(res)
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/7.2.0/math.js" integrity="sha512-O3GZu6Lz0va4Lk7IuF3CjKx5Jfxi35Gcx3oAjH7m7KRP5xvqorrInDpg3OFVJ6dMPn03vHiwgkgPT/hWfguVfQ==" crossorigin="anonymous"></script>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With