0

Here is an array

getMathResult(['200', '+', 300])

I need to convert all the data into a mathematical expression and execute it. How to do it?

ps we have to do it without

eval
  • is this from a job interview? sure does look like it – vsync May 11 '22 at 19:55
  • 1
    Does this answer your question? [Evaluating a string as a mathematical expression in JavaScript](https://stackoverflow.com/questions/2276021/evaluating-a-string-as-a-mathematical-expression-in-javascript) – PM 77-1 May 11 '22 at 19:56

2 Answers2

3

eval can do that:

"The eval() function evaluates JavaScript code represented as a string."

console.log(   eval('200' + '+' + 300)   )

Now for the array part:
(The spacing is for easier reading)

console.log(   eval(  ['200', '+', 300].join('')  )   )

You are welcome.


You've edited your question asking to do it without eval so:

let arr = ['200', '+', 300, '-', '50']
let sum = 0
let operator = '+' // assume as default 
let validOps = '+-' // place here all supported operations

for ( let item of arr ){
  if (+item){ // "+item" casts a string to a number, or to NaN
    if( operator == '+' )
      sum = sum + +item 
    else if ( operator == '-' )
      sum = sum - +item
  }
  else if( validOps.includes(item) )
    operator = item
}

console.log(sum)

And so on and so on for each operator you want to support :)

vsync
  • 118,978
  • 58
  • 307
  • 400
2

You could reduce the array and keep track of the previous operation. When you hit a new number, just apply the current operation and set it back to null.

const getMathResult = (tokens) =>
  tokens.reduce((acc, token, index, all) => {
    if (!isFinite(token)) return { ...acc, op: token }
    if (!acc.op) return { ...acc, op: null, total: +token }
    switch (acc.op) {
      case '+': return { ...acc, op: null, total: acc.total + (+token) }
      case '-': return { ...acc, op: null, total: acc.total - (+token) }
      case '*': return { ...acc, op: null, total: acc.total * (+token) }
      case '/': return { ...acc, op: null, total: acc.total / (+token) }
    }
    return acc;
  }, { op: null, total: 0 }).total;

console.log(getMathResult(['200', '+', 300]));   // 500
console.log(getMathResult([48, '/', 4]));        // 12
console.log(getMathResult([5, '+', 2, '*', 3])); // 21 (left-to-right vs PEMDAS)

Here is an alternative version that may be easier to follow:

const getMathResult = (tokens) =>
  tokens.reduce((acc, token, index, all) => {
    let { op, total } = acc;
    if (isFinite(token)) {
      if (op) {
        switch (op) {
          case '+': { total += +token; break; }
          case '-': { total -=  token; break; }
          case '*': { total *=  token; break; }
          case '/': { total /=  token; break; }
        }
      } else { total = +token }
    } else { op = token; }
    return { ...acc, op, total };
  }, { op: null, total: 0 }).total;

console.log(getMathResult(['200', '+', 300]));   // 500
console.log(getMathResult([48, '/', 4]));        // 12
console.log(getMathResult([5, '+', 2, '*', 3])); // 21 (left-to-right vs PEMDAS)
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132