【问题标题】:Loop through a Stack to get the sum遍历堆栈以获取总和
【发布时间】:2019-09-25 11:20:09
【问题描述】:

我目前正在使用 Javascript 编写计算器。被点击的按钮被存储在 Stack 中。 例如,我们点击“54”、“+”、“23”。那应该是77,对吧? 所以现在我的堆栈显示这个 ["54", "+", "23", "=", ""] 我希望堆栈的结果如下: [“54”、“+”、“23”、“=”、“”、“77”] 如果您也知道如何在 Stack 中删除空字符串,那就太好了。

const value = event.target.value;

            if(isNaN(parseInt(value, 10)))
            {
                stack.push(value)
                stack.push('')

            } else if(stack.length > 0)
            {
                stack[stack.length - 1] += '' + value; 
            }
            if (prevop == '=') {
                document.getElementById("textfield").value = "";
            }

            prevop = value;

我正在尝试实现她下面的逻辑以获得我想要的结果。

            var sum = 0;
            var stackLength = stack.length;
            for(var i = 0; i < stackLength; i++)
            {
                sum = sum + stack.pop();
                stack.push(sum);
            }

【问题讨论】:

    标签: javascript arrays stack


    【解决方案1】:

    您可以尝试使用eval。但请记住,eval 对代码注入很危险:

    function calc(stack){
        const i = stack.findIndex(x => x === '=');
        const expression = stack.slice(0, i).join('');
    
        stack[stack.length - 1] = '' + eval(expression);
    
        return stack; 
    }
    

    UPD:没有eval 的解决方案。请注意,此解决方案未考虑操作员优先级。

    function calc(stack) {
        let res = +stack[0];
    
        for (let i = 1; i < stack.length; i += 2) {
            const operator = stack[i];
            const rightNumber = stack[i + 1];
    
            switch (operator) {
                case '+': res += +rightNumber; break;
                case '-': res -= +rightNumber; break;
                case '*': res *= +rightNumber; break;
                case '/': res /= +rightNumber; break;
                case '=': stack[stack.length - 1] = '' + res; return stack;
            }
        }
    }
    

    【讨论】:

    • 能否提供一个不带 eval 的示例。
    • 看看Polish notation。也许先将堆栈转换成它然后进行操作会更好。它会给你一个根据优先级进行操作的可能性
    【解决方案2】:

    您可以使用第二个堆栈来保存中间结果,然后将该堆栈清空到输入数组的顶部。

    示例

    function evaluate(arr) {
        const array = [...arr];
        const stack = [];
        const pop = () => stack.pop();
        const shift = () => array.shift();
        const operators = {
            "+"() { return Number(pop()) + Number(shift()) },
            "-"() { return pop() - shift() },
            "*"() { return pop() * shift() },
            "/"() { return pop() / shift() },
            "="() { return pop()},
        };   
        while(array.length) {
            const val = shift();
            stack.push(operators[val] ? operators[val]() : val);
        }
        arr.push(pop());
        return arr;
    }
    
    // Examples
    console.log(evaluate(["10", "+", "20", "="]).join(" "));
    console.log(evaluate(["10", "*", "20", "="]).join(" "));
    console.log(evaluate(["10", "-", "20", "="]).join(" "));
    console.log(evaluate(["10", "/", "20", "="]).join(" "));
    console.log(evaluate([10, "+", 20, "+", 30,"="]).join(" "));

    添加优先级和嵌套括号。

    注意新版本假定数组以"="结尾

    function evaluate(array) {
      const operators = {  // operators must be in order of precedence
        "**"(){ return left() ** right() },
        "*"() { return left() * right() },
        "/"() { return left() / right() },
        "%"() { return left() % right() },
        "+"() { return left() + Number(right()) },
        "-"() { return left() - right() },
      }; 
      const order = Object.keys(operators);  
      const a = [...array];
      const index = (val, idx = i) => i = a.indexOf(val, idx);
      const left = () => a[i - 1], right = () => a[i + 1];
      const OK = () => a.length > 2;
      const brackets = () => {
        var i = -1;
        while ((i = index("(", i + 1)) > -1) {
          a.splice(i, 1);
          let depth = 1;
          const sub = [];
          while (depth) {
            const val = a.splice(i, 1)[0];
            val === "(" && depth++ || val === ")" && depth--;
            depth && sub.push(val);
          }
          a.splice(i, 0, evaluate(sub).pop());
        }
      }
      brackets();
      var i;
      while (OK() && order.length) {
        const op = order.shift(), func = operators[op];
        i = 0;
        while (OK() && index(op) > -1) { a.splice(i - 1, 3, func()) }
      }
      array.push(a[0])
      return array;
    }
    
    console.log(evaluate([10, "+", "(", 20, "-", 30, ")", "+", 20, "+", 20, "*", 30, "/", 30, "="]).join(""))

    【讨论】:

    • 抱歉,我看不出我是如何在当前结构中实现这一点的。您能否根据我制作的 for 循环提供一个示例。我忘了说我对 Javascript 很陌生。
    • @Zagros 只需将函数evaluate 添加到您的代码中并使用evaluate(stack) 调用它,结果将添加到stack 的末尾
    猜你喜欢
    • 2016-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多