交并集逻辑表达式解析工具

81 阅读1分钟
public static void main(String[] args) {
    Set<Integer> a = new HashSet<>();
    a.add(1);
    a.add(2);
    a.add(3);
    a.add(4);

    Set<Integer> b = new HashSet<>();
    b.add(3);
    b.add(4);
    b.add(5);

    Set<Integer> c = new HashSet<>();
    c.add(2);
    c.add(3);
    c.add(6);

    Set<Integer> d = new HashSet<>();
    d.add(3);
    d.add(7);
    d.add(8);

    Set<Integer> f = new HashSet<>();
    f.add(5);
    f.add(8);
    f.add(9);

    Set<Integer> result = calculateExpression("(c交d交f)并a", Map.of("a", a, "b", b, "c", c, "d", d, "f", f));
    System.out.println("最终结果: " + result);
}

public static Set<Integer> calculateExpression(String expression, Map<String, Set<Integer>> variableMap) {
    Stack<Set<Integer>> stack = new Stack<>();
    Stack<Character> operatorStack = new Stack<>();

    // 匹配变量、括号、操作符的正则表达式
    Pattern pattern = Pattern.compile("([a-zA-Z]+)|([()])|([交并])");
    Matcher matcher = pattern.matcher(expression);

    while (matcher.find()) {
        String variable = matcher.group(1);
        String bracket = matcher.group(2);
        String operator = matcher.group(3);

        if (variable!= null) {
            // 如果是变量,从映射中获取对应的集合,压入栈
            stack.push(variableMap.get(variable));
        } else if (bracket!= null) {
            if (bracket.equals("(")) {
                // 左括号,直接压入操作符栈
                operatorStack.push(bracket.charAt(0));
            } else {
                // 右括号,开始计算括号内的表达式
                // .peek 查看栈顶元素
                while (operatorStack.peek()!= '(') {
                    char op = operatorStack.pop();
                    performOperation(stack, op);
                }
                operatorStack.pop(); // 弹出左括号
            }
        } else if (operator!= null) {
            // 如果是操作符,根据其优先级等规则压入操作符栈
            while (!operatorStack.isEmpty() && hasHigherOrEqualPrecedence(operatorStack.peek(), operator.charAt(0))) {
                char op = operatorStack.pop();
                performOperation(stack, op);
            }
            operatorStack.push(operator.charAt(0));
        }
    }

    // 处理剩余的操作符
    while (!operatorStack.isEmpty()) {
        char op = operatorStack.pop();
        performOperation(stack, op);
    }

    return stack.pop();
}

private static void performOperation(Stack<Set<Integer>> stack, char operator) {
    List<Set<Integer>> operands = new ArrayList<>();

    int j = 0;
    // 收集连续相同操作符对应的所有操作数
    while (!stack.isEmpty() && (operator == '交' || operator == '并')) {
        j++;
        operands.add(stack.pop());
        if (j == 2) {
            break;
        }
    }
    Collections.reverse(operands);

    Set<Integer> result = null;
    if (!operands.isEmpty()) {
        result = operands.get(0);
        for (int i = 1; i < operands.size(); i++) {
            Set<Integer> currentOperand = operands.get(i);
            if (operator == '交') {
                result.retainAll(currentOperand);
            } else if (operator == '并') {
                result.addAll(currentOperand);
            }
        }
    }
    stack.push(result);
    System.err.println(result);
}

private static boolean hasHigherOrEqualPrecedence(char op1, char op2) {
    // 这里简单定义交的优先级高于并,你可以根据实际需要调整更复杂的优先级规则
    if (op1 == '交' && op2 == '交') {
        return true;
    }else return op1 == '并' && op2 == '并';
}