Question

I have a string that looks like this:

0,0,1,2,4,5,3,4,6

What I want returned is a String[] that was split after every 3rd comma, so the result would look like this:

[ "0,0,1", "2,4,5", "3,4,6" ]

I have found similar functions but they don't split at n-th amount of commas.

Was it helpful?

Solution

NOTE: while solution using split may work (last test on Java 17) it is based on bug since look-ahead in Java should have obvious maximum length. This limitation should theoretically prevent us from using + but somehow \G at start lets us use + here. In the future this bug may be fixed which means that split will stop working.

Safer approach would be using Matcher#find like

String data = "0,0,1,2,4,5,3,4,6";
Pattern p = Pattern.compile("\\d+,\\d+,\\d+");//no look-ahead needed
Matcher m = p.matcher(data);
List<String> parts = new ArrayList<>();
while(m.find()){
    parts.add(m.group());
}
String[] result = parts.toArray(new String[0]);

You can try to use split method with (?<=\\G\\d+,\\d+,\\d+), regex

Demo

String data = "0,0,1,2,4,5,3,4,6";
String[] array = data.split("(?<=\\G\\d+,\\d+,\\d+),"); //Magic :) 
// to reveal magic see explanation below answer
for(String s : array){
    System.out.println(s);
}

output:

0,0,1
2,4,5
3,4,6

Explanation

  • \\d means one digit, same as [0-9], like 0 or 3
  • \\d+ means one or more digits like 1 or 23
  • \\d+, means one or more digits with comma after it, like 1, or 234,
  • \\d+,\\d+,\\d+ will accept three numbers with commas between them like 12,3,456
  • \\G means last match, or if there is none (in case of first usage) start of the string
  • (?<=...), is positive look-behind which will match comma , that has also some string described in (?<=...) before it
  • (?<=\\G\\d+,\\d+,\\d+), so will try to find comma that has three numbers before it, and these numbers have aether start of the string before it (like ^0,0,1 in your example) or previously matched comma, like 2,4,5 and 3,4,6.

Also in case you want to use other characters then digits you can also use other set of characters like

  • \\w which will match alphabetic characters, digits and _
  • \\S everything that is not white space
  • [^,] everything that is not comma
  • ... and so on. More info in Pattern documentation

By the way, this form will work with split on every 3rd, 5th, 7th, (and other odd numbers) comma, like split("(?<=\\G\\w+,\\w+,\\w+,\\w+,\\w+),") will split on every 5th comma.

To split on every 2nd, 4th, 6th, 8th (and rest of even numbers) comma you will need to replace + with {1,maxLengthOfNumber} like split("(?<=\\G\\w{1,3},\\w{1,3},\\w{1,3},\\w{1,3}),") to split on every 4th comma when numbers can have max 3 digits (0, 00, 12, 000, 123, 412, 999).

To split on every 2nd comma you can also use this regex split("(?<!\\G\\d+),") based on my previous answer

OTHER TIPS

Obligatory Guava answer:

String input = "0,0,1,2,4,5,3,4,6";
String delimiter = ",";
int partitionSize = 3;

for (Iterable<String> iterable : Iterables.partition(Splitter.on(delimiter).split(s), partitionSize)) {
    System.out.println(Joiner.on(delimiter).join(iterable));
}

Outputs:

0,0,1
2,4,5
3,4,6

Try something like the below:

public String[] mySplitIntoThree(String str) 
{
    String[] parts = str.split(",");

    List<String> strList = new ArrayList<String>();

    for(int x = 0; x < parts.length - 2; x = x+3) 
    {
        String tmpStr = parts[x] + "," + parts[x+1] + "," + parts[x+2];

        strList.add(tmpStr);
    }

    return strList.toArray(new String[strList.size()]);
}

(You may need to import java.util.ArrayList and java.util.List)

Nice one for the coding dojo! Here's my good old-fashioned C-style answer:

If we call the bits between commas 'parts', and the results that get split off 'substrings' then:

n is the amount of parts found so far, i is the start of the next part, startIndex the start of the current substring

Iterate over the parts, every third part: chop off a substring.

Add the leftover part at the end to the result when you run out of commas.

List<String> result = new ArrayList<String>();
int startIndex = 0;
int n = 0;
for (int i = x.indexOf(',') + 1; i > 0; i = x.indexOf(',', i) + 1, n++) {
    if (n % 3 == 2) {
        result.add(x.substring(startIndex, i - 1));
        startIndex = i;
    }
}
result.add(x.substring(startIndex));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top