使用JS从等式中提取运算符和数字

Posted

技术标签:

【中文标题】使用JS从等式中提取运算符和数字【英文标题】:Extract operators and numbers from an equation using JS 【发布时间】:2021-10-06 20:37:37 【问题描述】:

我正在开发一个 jQuery 计算器,它具有如下所示的实时显示:

let liveDisplayString = $('#liveDisplay').val();
// ex. '42.5*30.6' or '7/2'

我试图通过运算符+-*/ 分离出数字,然后将列表项分配给变量以用于计算。我还需要抓住运算符,所以我需要另一个表达式来忽略 1-9 和小数。

我真的很难理解如何创建一个正则表达式以在.match() 中使用。

附:我对编程和 JS 语言还是很陌生

【问题讨论】:

您接受答案的速度太快了。您接受的答案很差,表明对正则表达式的基础知识缺乏了解。我建议您使用matchAllexec,并使用捕获组来分隔值。 【参考方案1】:

您可以使用String#split 和正则表达式来完成工作。

以下提取运算符+-*/

const value = '42.5*30.6+6-2/6';
const numbers = value.split(/[*]|[+]|[-]|[\/]/);
const operators = value.split(/[^-|+|\/|\*]/).filter(e => e);
console.log(numbers);
console.log(operators);

【讨论】:

运营商拆分似乎无法有效工作。我似乎能够提取的唯一运算符是“*”,而“-”运算符根本不拆分数字 @GarrettJH。我已经更新了正则表达式。它现在应该可以工作了。【参考方案2】:

解析表达式可能会变得相当复杂。

在您的情况下,如果表达式 总是 的形式为 <value> <operator> <value>(带或不带空格),您可以按运算符拆分:

const OPERATORS = 
    '*': (a, b) => a * b,
    '/': (a, b) => a * b,
    '+': (a, b) => a * b,
    '-': (a, b) => a * b,
;

function evaluate(input) 
    // Loop over the keys, e.g. '*', '/', ...
    for (const operator in OPERATORS) 
        // Split e.g. '1 + 2' into ['1 ', ' 2']
        // but if the operator is '*' and we have '1+2' we get ['1+2']
        const split = input.split(operator);
        if (split.length === 2) 
            // ^ There was exactly one <operator> in the string
            let [a, b] = split;
            // Trim, e.g. "42.5 " into "42.5" then parse as a float
            a = parseFloat(a.trim());
            b = parseFloat(b.trim());
            // Get the arrow function from OPERATORS and return the call result
            return OPERATORS[operator](a, b);
        
    
    throw new Error(`Invalid expression!`);


console.log(evaluate('42.5 * 30.6'));

如果您是 JS 新手,这可能已经开始看起来有点复杂,这仅适用于 &lt;value&gt; &lt;operator&gt; &lt;value&gt;。如果你真的想开始处理例如5 + 2 * 3 + 3,还有很多工作。

您可以简单地从左到右解析,例如[5, '+', 2, '*', 3, '+', 3],但记住操作顺序。您想将其评估为(5 + (2 * 3)) + 3 而不是((5 + 2) * 3) + 3。您需要在那里使用一种算法来正确“交换”二进制操作。但也许这是很久以后的话题了。


要实际使用 RegEx,这也是一种选择:

const input = '42.5 * 30.6';

const match = input.match(/^\s*(\d*\.\d+)\s*(\*|\/|\+|\-)\s*(\d*\.\d+)$/);
// Array destructuring, e.g. [0,1,2,3] results in a=1, op=2, b=3
const [, a, op, b] = match;
console.log('a', a);
console.log('op', op);
console.log('b', b);

RegEx 在任何地方都使用\s* 来表示“这里可以有空格,但不需要”,而(\d*\.\d+) 允许(十进制)数字,而(\*|\/|\+|\-) 想要a 运算符.我们需要用\ 对其进行转义,因为这些都是正则表达式中的特殊字符。

【讨论】:

感谢您的回答。第一部分现在绝对是我的头,我无法在 reg exp 部分很好地实现,但这可能是由于我在节点服务器中设置的其他限制。感谢您分解并解释正则表达式试图做什么。 正则表达式的好站点是RegExr。除了左侧边栏中的CheatsheetRegEx Reference,它还允许您立即测试您的正则表达式,甚至检查正则表达式本身及其产生的结果。我应该提到我的 RegExp 使用捕获组(将部分包装在 (...) 中),因此可以像例如match[1],我使用 destructuring 完成的。

以上是关于使用JS从等式中提取运算符和数字的主要内容,如果未能解决你的问题,请参考以下文章

如何从字符串中提取简单的数字表达式数字?

如果我理解正确:C# 等式运算符 ( == ) 和操作数的顺序

如何提取数字(以及比较形容词或范围)

按位运算从一个长的提取每个单独的词

在 ng-class 中结合三元运算符和等式语句

HBase 是不是支持对列表属性和不等式运算符进行索引?