我正在尝试模拟类似函数。假设我有这样的输入:
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>
逐步
-
var tree = extractEquation("12 + 6 * 3")
; -
"12 + 6 * 3".replace(/:?(w|d)+s*(*|/)s*:?(w|d)+/g, function(priorityOperation) { return "(" + priorityOperation + ")"; })
设置优先操作。结果是:12 + (6 * 3)
-
"12 + (6 * 3)".replace(/s/g, "")
将删除空间,结果是:12+(6*3)
-
[].reduce.call("12 + (6 * 3)", function(result, char){}, []);
将调用function(result, char){}
(其中result
是最后一个迭代的return
值,从[]
开始,char
是每个字符(。 - 第一次迭代
result = [], char = "1"
-
if ("1" === "(")
=>false
-
if ("1" === ")")
=>false
-
if (["+", "-", "*", "/"].includes("1"))
=>false
- 其他
-
if (![].length)
=>true
-
[].push("")
-
[""][0] += "1"
-
- 第二次迭代
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"
-
- 第三次迭代
result = ["12"], char = "+"
-
if ("+" === "(")
=>false
-
if ("+" === ")")
=>false
-
if (["+", "-", "*", "/"].includes("+"))
=>true
-
if (["12"].length && ["12"][0] is an operator)
=>false
-
["12"].push({operator: "+"})
-
- 第四次迭代
result = ["12", {"+"}], char = "("
-
if ("(" === "(")
=>true
-
["12", {"+"}].push([])
-
- 第五次迭代
result = [], char = "6"
-
if ("6" === "(")
=>false
-
if ("6" === ")")
=>false
-
if (["+", "-", "*", "/"].includes("6"))
=>false
- 其他
-
if (![].length)
=>true
-
[].push("")
-
[""][0] += "6"
-
- 第六次迭代
result = ["6"], char = "*"
-
if ("*" === "(")
=>false
-
if ("*" === ")")
=>false
-
if (["+", "-", "*", "/"].includes("*"))
=>true
-
if (["6"].length && ["6"][0] is an operator)
=>false
-
["6"].push({operator: "*"})
-
- 第七次迭代
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"
-
- 八个迭代
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