由于需要做表达式的可视化流程,在开始时,使用的是从左到右的解析方式,如下,可以看到有弊端,即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;
}
|