【问题标题】:Split by a comma that is not inside parentheses, skipping anything inside them用不在括号内的逗号分隔,跳过括号内的任何内容
【发布时间】:2015-06-23 00:09:08
【问题描述】:

我知道这可能是关于正则表达式的另一个话题,但尽管我搜索了它,但我无法得到明确的答案。所以这是我的问题 - 我有一个这样的字符串:

{1,2,{3,{4},5},{5,6}}

我正在删除最外面的括号(它们在输入中,我不需要它们),所以现在我有了这个:

1,2,{3,{4},5},{5,6}

现在,我需要将此字符串拆分为一个元素数组,将这些括号内的所有内容视为一个“无缝”元素:

Arr[0]    1
Arr[1]    2
Arr[2]    {3,{4},5}
Arr[3]    {5,6}

我尝试过使用前瞻来做到这一点,但到目前为止,我失败了(悲惨地)。就正则表达式而言,处理这些事情的最佳方式是什么?

【问题讨论】:

    标签: java regex string split


    【解决方案1】:

    如果应该将这样的元素放在一起,则不能这样做:{{1},{2}}。原因是 相当于解析平衡括号语言。这种语言是上下文无关的,不能使用正则表达式解析。处理此问题的最佳方法不是使用正则表达式,而是使用带有堆栈的 for 循环(堆栈提供解析上下文无关语言的能力)。在伪代码中我们可以这样做:

    for char in input
        if stack is empty and char is ','
            add substring(last, current position) to output array
            last = current index 
        if char is '{'
             push '{' on stack
        if char is '}'
             pop from stack
    

    此伪代码将根据需要构造数组,请注意,最好循环遍历给定字符串中字符的索引,因为您需要这些索引来确定要添加到数组的子字符串的边界。

    【讨论】:

      【解决方案2】:

      几乎接近要求。时间不多了。稍后将完成休息(单个逗号不正确)。
      正则表达式:,(?=[^}]*(?:{|$))
      检查正则表达式的有效性:转到http://regexr.com/

      要在 Java 中实现这种模式,有一点不同。 \ 需要在 { 和 } 之前添加。

      因此,Java 输入的正则表达式:,(?=[^\\}]*(?:\\{|$))

      String numbers = {1,2,{3,{4},5},{5,6}};
      numbers = numbers.substring(1, numbers.length()-1);
      String[] separatedValues = numbers.split(",(?=[^\\}]*(?:\\{|$))");
      System.out.println(separatedValues[0]);
      

      【讨论】:

        【解决方案3】:

        无法找到regex 的解决方案,但这里有一个非regex 的解决方案。它涉及在每个逗号之前解析数字(不在大括号中)(除非它是字符串中的最后一个数字)并解析字符串(在大括号中),直到找到该组的右大括号。

        如果找到正则表达式解决方案,我很乐意看到它。

        public static void main(String[] args) throws Exception {
            String data = "1,2,{3,{4},5},{5,6},-7,{7,8},{8,{9},10},11";
            List<String> list = new ArrayList();
            for (int i = 0; i < data.length(); i++) {
                if ((Character.isDigit(data.charAt(i))) ||
                    // Include negative numbers
                     (data.charAt(i) == '-') && (i + 1 < data.length() && Character.isDigit(data.charAt(i + 1)))) {
                    // Get the number before the comma, unless it's the last number
                    int commaIndex = data.indexOf(",", i);
                    String number = commaIndex > -1
                            ? data.substring(i, commaIndex)
                            : data.substring(i);
                    list.add(number);
                    i += number.length();
                } else if (data.charAt(i) == '{') {
                    // Get the group of numbers until you reach the final 
                    // closing curly brace
                    StringBuilder sb = new StringBuilder();
                    int openCount = 0;
                    int closeCount = 0;
                    do {
                        if (data.charAt(i) == '{') {
                            openCount++;
                        } else if (data.charAt(i) == '}') {
                            closeCount++;
                        }
                        sb.append(data.charAt(i));
                        i++;
                    } while (closeCount < openCount);
                    list.add(sb.toString());
                }
            }
        
            for (int i = 0; i < list.size(); i++) {
                System.out.printf("Arr[%d]: %s\r\n", i, list.get(i));
            }
        }
        

        结果:

        Arr[0]: 1
        Arr[1]: 2
        Arr[2]: {3,{4},5}
        Arr[3]: {5,6}
        Arr[4]: -7
        Arr[5]: {7,8}
        Arr[6]: {8,{9},10}
        Arr[7]: 11
        

        【讨论】:

        • 没有没有regex解决方案,语言是context-free
        • 您好,我对这段代码有一个问题——我怎样才能让它与负值一起工作——它要么删除带减号的,要么返回没有它的所有内容。我确信可以快速修复它,但我就是找不到。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-06-01
        • 2017-04-02
        • 1970-01-01
        • 2018-08-22
        • 1970-01-01
        • 2018-11-22
        • 2014-10-06
        相关资源
        最近更新 更多