Java: splitting a comma-separated string but ignoring commas in parentheses

后端 未结 4 548
無奈伤痛
無奈伤痛 2020-12-06 15:45

I have a string like this:

one,two,3,(4,five),six,(seven),(8,9,ten),eleven,(twelve,13,14,fifteen)

the above string should split into:

         


        
相关标签:
4条回答
  • 2020-12-06 16:29

    There is a relatively simple, one-line solution to this:

    String[] parts = input.split(",(?![^()]*\\))");
    
    0 讨论(0)
  • 2020-12-06 16:29

    Use Regex.

        String s = "one,two,3,(4,five),six,(seven),(8,9,ten),eleven,(twelve,13,14,fifteen)";
        Matcher m = Pattern.compile("[^,()]+|\\([^)]*\\)").matcher(s);
        while (m.find())
            System.out.println(m.group());
    
    0 讨论(0)
  • 2020-12-06 16:33

    The simplest solution to my opinion is to process the input string char-by-char:

    public static List<String> split(String input) {
        int nParens = 0;
        int start = 0;
        List<String> result = new ArrayList<>();
        for(int i=0; i<input.length(); i++) {
            switch(input.charAt(i)) {
            case ',':
                if(nParens == 0) {
                    result.add(input.substring(start, i));
                    start = i+1;
                }
                break;
            case '(':
                nParens++;
                break;
            case ')':
                nParens--;
                if(nParens < 0) 
                    throw new IllegalArgumentException("Unbalanced parenthesis at offset #"+i);
                break;
            }
        }
        if(nParens > 0)
            throw new IllegalArgumentException("Missing closing parenthesis");
        result.add(input.substring(start));
        return result;
    }
    

    Example:

    split("one,two,3,(4,five),six,(seven),(8,9,ten),eleven,(twelve,13,14,fifteen)") ->
    [one, two, 3, (4,five), six, (seven), (8,9,ten), eleven, (twelve,13,14,fifteen)]
    

    As a free bonus, this solution also counts nested parentheses if necessary:

    split("one,two,3,(4,(five,six),seven),eight") ->
    [one, two, 3, (4,(five,six),seven), eight]
    

    Also it checks whether parentheses are balanced (every open parenthesis has the corresponding closing one).

    0 讨论(0)
  • 2020-12-06 16:42

    here you go... :)

    import java.util.ArrayList;
    import java.util.List;
    import java.util.StringTokenizer;
    
    /**
     *
     * @author S1LENT W@RRIOR
     */
    public class Tokenizer {
    
        public static void main(String... args) {
    
            List<String> tokens = new ArrayList(); // List to store tokens
    
            String string = "one,two,3,(4,five),six,(seven),(8,9,ten),eleven,(twelve,13,14,fifteen)"; // input string
            StringTokenizer tokenizer = new StringTokenizer(string, "(),", true); // tokenize your string on the basis of these parentheses 
    
            while (tokenizer.hasMoreElements()) { // iterate over tokens
    
                String aToken = (String) tokenizer.nextElement(); // get a token
    
                if (aToken.equals("(")) { // if token is the begining of a parenthisis
                    StringBuilder sb = new StringBuilder(aToken);
                    String nextToken = (String) tokenizer.nextElement(); // get next token
                    while (!nextToken.equals(")")) { // iterate over next tokens untill you find the ending bracket
                        sb.append(nextToken);
                        nextToken = (String) tokenizer.nextElement();
                    }
                    sb.append(")");
    
                    tokens.add(sb.toString()); // add to tokens list
                } else if(aToken.equals(",")) { // need this to avoid adding commas
                    // do nothing
                } else {
                    tokens.add(aToken); // add to tokens list
                }
            }
    
            for(String aToken: tokens) { // print all tokens
                System.out.println(aToken);
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题