使用运算符相对于括号分割字符串

时间:2013-08-21 22:15:13

标签: java regex string split

我希望以下字符串被(相对于括号对)最外层运算符(在这种情况下:'+')拆分:

1: "((20 + 20) + a)"
2: "(20 + ((20 + 20) + 20))

结果应该是这样的:

1: "((20 + 20) "         and           " a)"
2: "(20 "                and           " ((20 + 20) + 20))"

1 个答案:

答案 0 :(得分:2)

你不能用正则表达式做到这一点,但你可以尝试这样的事情:

// locations of top-level operators:
List<Integer> locations = new ArrayList<Integer>();

int level = 0;

for (int i = 0; i < str.length(); i++) {
    char c = str.charAt(i);

    if (c == '(') {
        level++;
    }
    else if (c == ')') {
        level--;
    } 
    else if ("+-*/".indexOf(c) >= 0 && level == 1) {
        locations.add(i);
    }
}

然后,您可以使用substring()locations中的任何内容“拆分”字符串。


如果总是希望拆分最外层的运算符(例如,在+中的(((a + 1)))上拆分),那么事情会变得有点棘手,但是你的整体方法并没有不必大幅改变。想到的一个想法是构建一个Map<OperatorData, Integer>(其中OperatorData是一个包含运算符标记的类(例如+)和一个表示它嵌套的距离的int)映射到位置在字符串中。基于嵌套级别,OperatorData可以是Comparable

OperatorData可能看起来像这样:

class OperatorData implements Comparable<OperatorData> {
    private String token;
    private int level;

    // constructor etc.

    @Override
    public int compareTo(OperatorData other) {
        return Integer.compare(level, other.level);
    }
}

然后,您可以浏览此地图并拆分嵌套级别最低的运算符。方法可能如下所示:

// location of top-level operators:
Map<OperatorData, Integer> operators = new HashMap<>();

int level = 0;
int i = 0;
while (i < str.length()) {
    char c = str.charAt(i);

    if (c == '(') {
        level++;
    } else if (c == ')') {
        level--;
    } else if (isOperatorChar(c)) {
        final int index = i;
        StringBuilder token = new StringBuilder();
        token.append(c);

        while (isOperatorChar(c = str.charAt(i + 1))) {
            token.append(c);
            i++;
        }

        operators.put(new OperatorData(token.toString(), level), index);
    }

    i++;
}

// find smallest OperatorData in map