在javascript中评估公式

时间:2016-10-04 06:28:18

标签: javascript html json

我有一个公式和一个包含变量的对象作为键 我的目标是

{
 xyz:{
     v:20
  },
 ab:{
     v:2
  },
 y:{
     v:30
  },
 z:{
     v:40
  },

}

现在我必须评估公式

例如

xyz+ab*(y+z)
  

结果:20 + 2 *(30 + 40)

任何优化的解决方案?

  
    

请注意,密钥的形式为"字符...字符"     例如。 ABC..XY12

         

更新:实际对象是

  
{
 pnl..xyz:{
     v:20
  },
 pxl..ab:{
     v:2
  },
 pnl..y:{
     v:30
  },
 pxl..z:{
     v:40
  },

}

,公式是

pnl..xyz+pxl..ab*(pnl..y+pxl..z)

3 个答案:

答案 0 :(得分:2)

您可以使用正则表达式查找变量名称并发布可以使用eval

的帖子

示例

var data={xyz:{v:20},ab:{v:2},y:{v:30},z:{v:40},abc12:{v:12},"abc..bc":{v:31}};

function processOperation(str) {
  var formula = str;
  var operatios = /[+\-\*\/\(\)]/g;
  var keys = formula.split(operatios);
  keys.forEach(function(k) {
    if (k && data[k]) formula = formula.replace(k, data[k].v)
  });
  console.log(formula);
  return eval(formula)
}

var formula1 = "xyz+ab*(y+z)"
console.log(processOperation(formula1))

var formula2 = "xyz+ab*(y+z)-abc12"
console.log(processOperation(formula2))

var formula3 = "xyz+ab*(y+z)-12"
console.log(processOperation(formula3))

var formula4 = "xyz+ab*(y+z)-abc..bc"
console.log(processOperation(formula4))

答案 1 :(得分:1)

您可以编写自己的自定义解析器和求值程序,但是会出现大量边缘情况,验证和运算符优先级情况 已搞定。 我建议不要重新发明轮子,并使用math.js,它是一个轻量级的专用库,用于javascript中的数学。 以下是如何在一行中完成公式评估。



var scope = { xyz : 20,  ab : 2, y : 30, z : 40 };
var answer = math.eval('xyz+ab*(y+z)', scope); 
console.log('The answer is:' + answer);

<script src="http://cdnjs.cloudflare.com/ajax/libs/mathjs/3.5.3/math.min.js"></script>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

此函数将替换提供的obj字符串中提供的formula的键。它是咖喱的,所以你可以重复使用不同的变量值的相同公式。

&#13;
&#13;
const obj = {
 xyz:{ v:20 },
 ab:{ v:2 },
 y:{ v:30 },
 z:{ v:40 }
}

const obj2 = {
 'pnl..xyz':{ v:20 },
 'pxl..ab':{ v:2 },
 'pnl..y':{ v:30 },
 'pxl..z':{ v:40 },
}

 /*
 * evalFormula :: String -> {key:{v:Int}} -> String
 *
 * replace the formula string with the obj values
*/
const evalFormula = formula => obj => {
  // get the keys
  const keys = Object.keys(obj)
  // sort keys by length so we replace the longer strings first
  keys.sort(sortBy('length'))
  // reduce the keys into the formula
  return keys.reduce((str, key) => 
    // replace the key with it's corresponding value each iteration
    str.replace(stringToRegex(key, 'g'), obj[key].v)
  , formula)
}

// get a regular expression from an input string
const stringToRegex = (str, modifiers) => 
  new RegExp(str.replace(/([\.\^\$\*\+\-\?\(\)\[\]\{\}\\])/g, '\$1'), modifiers)

const sortBy = prop => (a, b) => a[prop] > b[prop] ? -1 : a[prop] < b[prop] ? 1 : 0

// this is the executable function
const execFormula = evalFormula('xyz+ab*(y+z)')
const otherFormula = evalFormula('pnl..xyz+pxl..ab*(pnl..y+pxl..z)')

console.log(
  execFormula(obj),
  otherFormula(obj2)
)
&#13;
&#13;
&#13;

编辑。

你只需要为你的钥匙中的非法字符添加一点逃脱,然后创建一个新的公式并传入新的obj