Gunjan Anshul
Gunjan Anshul

Reputation: 103

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)

Upvotes: 3

Views: 117

Answers (3)

Terry Lennox
Terry Lennox

Reputation: 30705

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>

Upvotes: 1

Gunjan Anshul
Gunjan Anshul

Reputation: 103

Math.js evaluate function works fine, but when values like 3.2477216E7 comes which contains alphabet "E", then it breaks. can u please let me know, how to handle that.

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: 3.2477216E7, RunHrs: 1, RunMins: 0, RunSecs: 3.2477063E7}

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, 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>

Upvotes: 0

Agnius Vasiliauskas
Agnius Vasiliauskas

Reputation: 11277

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.

Upvotes: 1

Related Questions