为短路运算符布尔表达式添加括号

该博客讨论了在实现表达式可视化流程时遇到的运算符优先级问题,例如A||B&&C应当先计算B&&C。作者通过Java和JavaScript代码示例展示了如何通过添加括号来正确处理运算顺序,确保前端能够正确解析表达式。主要涉及逻辑运算符的处理和字符串操作。
摘要由CSDN通过智能技术生成

由于需要做表达式的可视化流程,在开始时,使用的是从左到右的解析方式,如下,可以看到有弊端,即A || B && C应该是先计算B && C再与A||,但从左到右就变为了先A || B 再 && C,导致结果不正确。可以进行测试:true|| false && false;从左到右是false,但实际上结果是true;故需要对其进行解析,解析为A || (B && C)这样前端才能够正确解析;

在这里插入图片描述

Java版代码

/**
 * @author LaiYongBin
 * @date 创建于 2022/4/18 19:29
 * @apiNote DO SOMETHING
 */
public class Test {
    
    public static void main(String[] args) {
        String s = "A||B&&C&&(A&&D||T&&S)||F&&D";
        System.out.println(build(s));
    }

    public static String build(String param) {
        param = param.replace(" ", "");
        param = param.replace("&&", " && ");
        param = param.replace("||", " || ");
        List<String> stringList = allParentheses(param);
        // 将 && 加上括号, 括号里的部分不加
        String toString = putParentheses(param);
        for (String now : stringList) {
            toString = toString.replace(now, build(now));
        }
        return toString;
    }

    public static String putParentheses(String param) {
        int left = 0;
        // 是否有自己加的左括号
        boolean haveKuo = false;
        char[] toCharArray = param.toCharArray();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < toCharArray.length; i++) {
            char nowChar = toCharArray[i];
            sb.append(nowChar);
            if (nowChar == '(') {
                left++;
                continue;
            }
            if (nowChar == ')') {
                left--;
            }
            if (left != 0 || nowChar != ' ') {
                continue;
            }

            if (!haveKuo && (i + 4 < toCharArray.length) && toCharArray[i + 4] == '&') {
                sb.append('(');
                haveKuo = true;
            } else if (haveKuo && (i + 1 >= toCharArray.length || toCharArray[i + 1] == '|')) {
                sb.append(')');
                haveKuo = false;
            }
        }
        if (haveKuo) {
            sb.append(')');
        }
        return sb.toString();
    }

    /**
     * 获取括号的所有内容
     */
    public static List<String> allParentheses(String eval) {
        // true || (false && false)
        // 左括号的数量
        int left = 0;
        // 是否已经匹配到
        boolean b = false;
        StringBuilder s = new StringBuilder();
        List<String> resultList = new ArrayList<>();
        for (char c : eval.toCharArray()) {
            if (c == '(') {
                left++;
                b = true;
            } else if (c == ')') {
                left--;
            }
            if (b) {
                s.append(c);
            }
            if (b && (left == 0)) {
                resultList.add(s.substring(1, s.length() - 1));
                s = new StringBuilder();
                b = false;
            }
        }
        return resultList;
    }

}

JS代码

// 方法入口
function build(param) {
    param = param.replaceAll(" ", "");
    param = param.replaceAll("&&", " && ");
    param = param.replaceAll("||", " || ");
    const stringList = allParentheses(param);
    // 将 && 加上括号, 括号里的部分不加
    let res = putParentheses(param);
    for (let i = 0; i < stringList.length; i++) {
        const now = stringList[i];
        // 递归
        res = res.replaceAll(now, build(now));
    }
    return res;
}


function putParentheses(param) {
    // 已匹配到的括号数
    let leftBrackets = 0;
    // 是否有自己加的左括号
    let haveKuo = false;
    let result = "";
    for (let i = 0; i < param.length; i++) {
        const nowChar = param[i];
        result += nowChar;
        if (nowChar === '(') {
            leftBrackets++;
            continue;
        }
        if (nowChar === ')') {
            leftBrackets--;
        }
        if (leftBrackets !== 0 || nowChar !== ' ') {
            continue;
        }

        if (!haveKuo && (i + 4 < param.length) && param[i + 4] === '&') {
            result += "(";
            haveKuo = true;
        } else if (haveKuo && (i + 1 >= param.length || param[i + 1] === '|')) {
            result += ")";
            haveKuo = false;
        }
    }
    if (haveKuo) {
        result += ")";
    }
    return result;
}

/**获取所有外层括号的值*/
function allParentheses(param) {
    // true || (false && false)
    // 左括号的数量
    let leftBrackets = 0;
    // 是否已经匹配到
    let isMatched = false;
    let s = "";
    const resultList = [];
    for (let i = 0; i < param.length; i++) {
        const c = param[i];
        if (c === '(') {
            leftBrackets++;
            isMatched = true;
        } else if (c === ')') {
            leftBrackets--;
        }
        if (isMatched) {
            s += c;
        }
        if (isMatched && (leftBrackets === 0)) {
            resultList.push(s.substring(1, s.length - 1));
            s = "";
            isMatched = false;
        }
    }
    return resultList;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

原来你是小幸运

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值