如何计算字符表达的数组(例如eval)



我正在尝试模拟类似函数。假设我有这样的输入:

arr = [
"1" ,
"+" ,
"(" ,
"33" ,
"+" ,
"44" ,
")" ,
"+" ,
"2" ,
"+" ,
"(" ,
"55" ,
"+" ,
"66" ,
")" ,
"="
]

现在我想在不使用eval

的情况下像1+(33+44)+2+(55+66)=一样计算它

我尝试了以下类似的事情,没有结果:

let result = 0;
  for (let i = 0; i < arr.length; i++) {
    var expr = arr[i];
    if (expr == '+' || expr == "-" || expr == "*" || expr == "(" || expr == ")") {
      if (expr == "(") {
        for (let j = i; j < arr.length; j++) {
          if(expr == "+"){
          }else if(expr == "-"){
          }else if(expr == "*"){
          }else if (expr == ")") {
            i = j+1;
            break;
          }else{
            result = result + parseFloat(expr);
          }
        }
      }
    } else {
      result = result + parseFloat(expr);
    }
    console.log(result)

我删除了一些我尝试的代码,因为它给了我太多的错误。谁可以帮我这个事。需要评论以获取更多详细信息。预先感谢。

您可以采用一种简化的方法,将嵌套数组用作级别的堆栈(由括号表示,仅使用二进制操作员并省略=(,因为这不是必需的。最后进行了所有开放计算。

这是一个具有箭头功能的对象,并使用Unary Plus +从字符串中获取数字。那么其他操作员不需要这一点,因为使用这些操作员使用这些操作员将值胁到数字。+也适用于字符串。

{
    '+': (a, b) => +a + +b
}

其余的很简单。如果发现了一个开放的父母,则将堆栈的新级别进行操作,并将所有令牌收集到此级别,直到找到闭合括号为止,然后计算级别并将值返回到级别之前。

>

calculate获取堆栈的三个项目,并执行具有左右值和中间操作员的操作。结果在索引零的数组中返回。

对于一单位减去,您可以检查并删除此项目并更新下一个值,具体取决于找到的负数。

function evaluate(string) {
    function calculate(array) {
        function removeUnaryMinus(array, offset) {
            var nonMinusIndex = array.findIndex((s, i) => i >=offset && s !== '-');
            array.splice(offset, nonMinusIndex - offset);
            if (nonMinusIndex % 2) array[offset] *= -1;
        }
        removeUnaryMinus(array, 0);
        while (array.length > 2) {
            removeUnaryMinus(array, 2);                    
            array.splice(0, 3, ops[array[1]](array[0], array[2]));
        }
        return array[0];
    }
    var ops = {
            '+': (a, b) => +a + +b,
            '-': (a, b) => a - b,
            '*': (a, b) => a * b,
            '/': (a, b) => a / b
        },
        stack = [[]],
        level = 0;
    string
        .split(/([+-*/()])/)
        .filter(s => s && s !== ' ')
        .forEach(token => {
            if (!token || token === '=') return;
            if (token === '(') {
                ++level;
                stack[level] = [];
                return;
            }
            if (token === ')') {
                --level;
                stack[level].push(calculate(stack[level + 1]));
                return;
            }
            stack[level].push(token);
        });
    return calculate(stack[0]);
}
console.log(evaluate('12 + 3'));                  //   15
console.log(evaluate('-(12 + -23) * (-4 + -7)')); // -121

我最近偶然发现了一个类似的问题,不得不提出自己的解决方案。该代码由2个函数组成,一个将代码转换为功能树,另一个将执行它。我已经有所更改以满足您的需求:

var operations = {
  '+': function(left, right) {
    return left + right;
  },
  '-': function(left, right) {
    return left - right;
  },
  '/': function(left, right) {
    return left / right;
  },
  '*': function(left, right) {
    return left * right;
  }
};
var tree = extractEquation("1+(33+44)+2+(55+66)");
console.log(resolveTree(tree));
console.log(tree);
/**
 * Runs a parsed mathematical expression
 * @param {Array<Array|{}|string>} functionTree expression in tree form
 * @returns {number} result of the expression
 */
function resolveTree(functionTree) {
  var operator = "+";
  return functionTree.reduce(function(result, item) {
    if (item instanceof Array) {
      return operations[operator](result, resolveTree(item));
    } else if (typeof item === "object") {
      operator = item.operator;
      return result;
    } else {
      return operations[operator](result, +item);
    }
  }, 0);
}
/**
 * Parses a mathematical expression
 * @param {string} expr expression in text form
 * @returns {Array<Array|{}|string>} expression in tree form
 */
function extractEquation(txt) {
  var root = [];
  var result = [].reduce.call(txt.replace(/:?(w|d)+s*(*|/)s*:?(w|d)+/g, function(priorityOperation) {
    return "(" + priorityOperation + ")";
  }).replace(/s/g, ""), function(result, char) {
    if (char === "(") {
      var newResult = [];
      newResult.parent = result;
      result.push(newResult);
      return newResult;
    } else if (char === ")") {
      if ("parent" in result) return result.parent;
      else throw SyntaxError("Found ) but missing (");
    } else if (Object.keys(operations).includes(char)) {
      if (result.length && typeof result[result.length - 1] !== "string" && "operator" in result[result.length - 1]) throw SyntaxError("Double operator");
      result.push({
        operator: char
      });
    } else {
      if (!result.length) result.push("");
      else if (typeof result[result.length - 1] !== "string" && "operator" in result[result.length - 1]) result.push("");
      result[result.length - 1] += char;
    }
    return result;
  }, root);
  if (result !== root) throw SyntaxError("Unclosed (");
  return root;
}

这是一个更具交互的示例:

var operations = {
  '+': function(left, right) {
    return left + right;
  },
  '-': function(left, right) {
    return left - right;
  },
  '/': function(left, right) {
    return left / right;
  },
  '*': function(left, right) {
    return left * right;
  }
};
document.getElementById("input").addEventListener("input", function() {
  document.getElementById("tree").innerHTML = "";
  try {
    var tree = extractEquation(document.getElementById("input").value);
    document.getElementById("result").textContent = resolveTree(tree);
    document.getElementById("error").textContent = "";
    fixUITree(document.getElementById("tree"), tree);
  } catch (err) {
    document.getElementById("error").textContent = err.message || err;
    document.getElementById("result").textContent = "";
  }
});
function fixUITree(dom, tree) {
  tree.forEach(function(item) {
    if (item instanceof Array) {
      fixUITree(dom.appendChild(document.createElement("ul")), item);
    } else if (typeof item === "object") {
      dom.appendChild(document.createElement("li")).textContent = item.operator;
    } else {
      dom.appendChild(document.createElement("li")).textContent = item;
    }
  }, 0);
}
/**
 * Runs a parsed mathematical expression
 * @param {Array<Array|{}|string>} functionTree expression in tree form
 * @returns {number} result of the expression
 */
function resolveTree(functionTree) {
  var operator = "+";
  return functionTree.reduce(function(result, item) {
    if (item instanceof Array) {
      return operations[operator](result, resolveTree(item));
    } else if (typeof item === "object") {
      operator = item.operator;
      return result;
    } else {
      return operations[operator](result, +item);
    }
  }, 0);
}
/**
 * Parses a mathematical expression
 * @param {string} expr expression in text form
 * @returns {Array<Array|{}|string>} expression in tree form
 */
function extractEquation(txt) {
  var root = [];
  var result = [].reduce.call(txt.replace(/:?(w|d)+s*(*|/)s*:?(w|d)+/g, function(priorityOperation) {
    return "(" + priorityOperation + ")";
  }).replace(/s/g, ""), function(result, char) {
    if (char === "(") {
      var newResult = [];
      newResult.parent = result;
      result.push(newResult);
      return newResult;
    } else if (char === ")") {
      if ("parent" in result) return result.parent;
      else throw SyntaxError("Found ) but missing (");
    } else if (Object.keys(operations).includes(char)) {
      if (result.length && typeof result[result.length - 1] !== "string" && "operator" in result[result.length - 1]) throw SyntaxError("Double operator");
      result.push({
        operator: char
      });
    } else {
      if (!result.length) result.push("");
      else if (typeof result[result.length - 1] !== "string" && "operator" in result[result.length - 1]) result.push("");
      result[result.length - 1] += char;
    }
    return result;
  }, root);
  if (result !== root) throw SyntaxError("Unclosed (");
  return root;
}
#result {
  color: green;
}
#error {
  color: red;
}
<input id="input" type="text">
<span id="result"></span>
<span id="error"></span>
<ul id="tree">
</ul>

逐步

  1. var tree = extractEquation("12 + 6 * 3");
  2. "12 + 6 * 3".replace(/:?(w|d)+s*(*|/)s*:?(w|d)+/g, function(priorityOperation) { return "(" + priorityOperation + ")"; })设置优先操作。结果是:12 + (6 * 3)
  3. "12 + (6 * 3)".replace(/s/g, "")将删除空间,结果是:12+(6*3)
  4. [].reduce.call("12 + (6 * 3)", function(result, char){}, []);将调用function(result, char){}(其中result是最后一个迭代的return值,从[]开始,char是每个字符(。
  5. 第一次迭代result = [], char = "1"
    • if ("1" === "(") => false
    • if ("1" === ")") => false
    • if (["+", "-", "*", "/"].includes("1")) => false
    • 其他
    • if (![].length) => true
    • [].push("")
    • [""][0] += "1"
  6. 第二次迭代result = ["1"], char = "2"
    • if ("2" === "(") => false
    • if ("2" === ")") => false
    • if (["+", "-", "*", "/"].includes("2")) => false
    • 其他
    • if (![].length) => false
    • if ([""][0] is an operator) => false
    • ["1"][0] =" 2"
  7. 第三次迭代result = ["12"], char = "+"
    • if ("+" === "(") => false
    • if ("+" === ")") => false
    • if (["+", "-", "*", "/"].includes("+")) => true
    • if (["12"].length && ["12"][0] is an operator) => false
    • ["12"].push({operator: "+"})
  8. 第四次迭代result = ["12", {"+"}], char = "("
    • if ("(" === "(") => true
    • ["12", {"+"}].push([])
  9. 第五次迭代result = [], char = "6"
    • if ("6" === "(") => false
    • if ("6" === ")") => false
    • if (["+", "-", "*", "/"].includes("6")) => false
    • 其他
    • if (![].length) => true
    • [].push("")
    • [""][0] += "6"
  10. 第六次迭代result = ["6"], char = "*"
    • if ("*" === "(") => false
    • if ("*" === ")") => false
    • if (["+", "-", "*", "/"].includes("*")) => true
    • if (["6"].length && ["6"][0] is an operator) => false
    • ["6"].push({operator: "*"})
  11. 第七次迭代result = ["6", {"*"}], char = "3"
    • if ("3" === "(") => false
    • if ("3" === ")") => false
    • if (["+", "-", "*", "/"].includes("3")) => false
    • 其他
    • if (!["6", {"*"}].length) => false
    • if (["6", {"*"}] is an operator) => true
    • ["6", {"*"}].push("")
    • ["6", {"*"}] += "3"
  12. 八个迭代result = ["6", {"*"}, "3"], char = ")"
    • if (")" === "(") => false
    • if (")" === ")") => true
    • return ["12", {"+"}, ["6", {"*"}, "3"]]
function addbits(s){
    var total= 0, s= s.match(/[+-]*(.d+|d+(.d+)?)/g) || [];
    while(s.length){
        total+= parseFloat(s.shift());
    }
    return total;
} 
   let arr = [
    "1" ,
    "+" ,
    "(" ,
    "33" ,
    "+" ,
    "44" ,
    ")" ,
    "+" ,
    "2" ,
    "+" ,
    "(" ,
    "55" ,
    "+" ,
    "66" ,
    ")" ,
    "="
    ]
let arr_string = arr.join(''); // you will get here "1+(33+44)+2+(55+66)="
let finalStr = arr_string.replace('=','');
addbits(finalStr); // output will be 201

相关内容

最新更新