正则表达式来帮助计算字符串中的括号值

时间:2018-02-21 00:10:58

标签: javascript regex

目前,我将此代码用于字符串...

中的总括号值
if ((string.match(/\((\d+)\)/g)||[]).length > 0) {
    var total = 0;
    string.replace(/\((\d+)\)/g, function(outerValue, innerValue){
        if (!isNaN(innerValue.toString().trim())) {
            total = total + Number(innerValue.toString().trim());
        }
    });

    value = total;
}

...所以字符串......

(2) dark chocolate, (2) milk chocolate, and (1) white chocolate

...总计5。

不愿意单独留下,我认为如果我能够有点发型并解释不同类型的操作会很酷,那么有人可以写作。

(2) dark + (2) milk - (1) white
    -or-
(2) dark and (2) milk minus (1) white

所以我把代码改为......

if ((string.match(/\((\d+)\)/g)||[]).length > 0) {
    var total = 0;
    string.replace(/^\((\d+)\)|and\s\((\d+)\)|plus\s\((\d+)\)|\+\s\((\d+)\)/g, function(outerValue, innerValue){
        if (!isNaN(innerValue.toString().trim())) {
            total = total + Number(innerValue.toString().trim());
        }
    });

    value = total;
}

...但是innerValue返回为undefined。当我在regex101.com中使用验证器进行测试时,我能够提取值,但不能在Javascript中进行。

我做错了什么?

P.S。显然,我的代码不完整(除了错误)。最后,我会列出所有操作员的可能性(例如," +","加",""," less", "减去"," - "等等)并检查outerValue中的字符串以确定运算符。当然,我需要在句子中编写逗号的逻辑(例如,允许句子中的单个操作符并将操作应用于每个项目。)

3 个答案:

答案 0 :(得分:2)

你的论点名称(outerValue, innerValue)并不准确。替换函数的参数是

function replace(match, p1, p2, ..., pn, offset, string)

所以你有

     p1               p2              p3            p4
      |               |               |             |   
/^\((\d+)\)|and\s\((\d+)\)|plus\s\((\d+)\)|\+\s\((\d+)\)/g
                              |
                            match

因此,当您通过替换函数运行(2) dark and (2) milk minus (1) white时:

第一场比赛"(2)"具有p1=2,因为它对应于正则表达式中的第一个括号集,即第一个组。然后你有p2=undefined, p3=undefined, p4=undefined
下一场比赛"和(2)"已p1=undefined,因为这与正则表达式中的第二个或组匹配,因此p1=undefined, p2=2, p3=undefined, p4=undefined

请参阅https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_function_as_a_parameter

答案 1 :(得分:0)

我建议构建一个解释字符串的添加解析器。我是用户regexps从文本中提取令牌((1) => 1- => -)并将其传递给解析器。它将跟踪值和运算符并执行计算。

此主题可能相关:https://stackoverflow.com/a/380487/580346

答案 2 :(得分:0)

辣椒的解释非常有帮助,他在回复中的后续建议也是如此。灵感探索一些变化,我最终编码如下:

if ((string.match(/\((\d+)\)/g)||[]).length > 0) {
    var total = 0;

    string.match(/^\((\d+)\)|,\s+\((\d+)\)|and\s+\((\d+)\)|plus\s+\((\d+)\)|\+\s+\((\d+)\)|\-\s+\((\d+)\)|minus\s+\((\d+)\)|less\s+\((\d+)\)|subtract\s+\((\d+)\)|times\s+\((\d+)\)|multiply\s+\((\d+)\)|x\s+\((\d+)\)|\*\s+\((\d+)\)/g).forEach(function(element, index){
        element.replace(/\((\d+)\)/g, function(m, p){
            if (!isNaN(p.toString().trim())) {
                p = Number(p);

                if (element.match(/^(minus|less|substract|\-)/g)) {
                    total = total - p;
                }
                else if (element.match(/^(times|multiply|x|\*)/g)) {
                    total = total * p;
                }
                else {
                    total = total + p;
                }
            }
        });
    });
}

我确信这是一种更有效的方式,但对于我迄今为止最深入的RegEx潜水,鉴于它确实有效,我认为这是一个良好的开端。