Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to process two Array Objects without using EVAL

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)
like image 949
Gunjan Anshul Avatar asked May 04 '26 18:05

Gunjan Anshul


2 Answers

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.

like image 94
Agnius Vasiliauskas Avatar answered May 06 '26 08:05

Agnius Vasiliauskas


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>
like image 29
Terry Lennox Avatar answered May 06 '26 07:05

Terry Lennox



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!