Splitting a string at every n-th character

JavaRegexStringSplit

Java Problem Overview


In JavaScript this is how we can split a string at every 3-rd character

"foobarspam".match(/.{1,3}/g)

I am trying to figure out how to do this in Java. Any pointers?

Java Solutions


Solution 1 - Java

You could do it like this:

String s = "1234567890";
System.out.println(java.util.Arrays.toString(s.split("(?<=\\G...)")));

which produces:

[123, 456, 789, 0]

The regex (?<=\G...) matches an empty string that has the last match (\G) followed by three characters (...) before it ((?<= ))

Solution 2 - Java

Java does not provide very full-featured splitting utilities, so the Guava libraries do:

Iterable<String> pieces = Splitter.fixedLength(3).split(string);

Check out the Javadoc for Splitter; it's very powerful.

Solution 3 - Java

import java.util.ArrayList;
import java.util.List;

public class Test {
	public static void main(String[] args) {
		for (String part : getParts("foobarspam", 3)) {
			System.out.println(part);
		}
	}
	private static List<String> getParts(String string, int partitionSize) {
		List<String> parts = new ArrayList<String>();
		int len = string.length();
		for (int i=0; i<len; i+=partitionSize)
		{
			parts.add(string.substring(i, Math.min(len, i + partitionSize)));
		}
		return parts;
	}
}

Solution 4 - Java

As an addition to Bart Kiers answer I want to add that it is possible instead of using the three dots ... in the regex expression which are representing three characters you can write .{3} which has the same meaning.

Then the code would look like the following:

String bitstream = "00101010001001010100101010100101010101001010100001010101010010101";
System.out.println(java.util.Arrays.toString(bitstream.split("(?<=\\G.{3})")));

With this it would be easier to modify the string length and the creation of a function is now reasonable with a variable input string length. This could be done look like the following:

public static String[] splitAfterNChars(String input, int splitLen){
	return input.split(String.format("(?<=\\G.{%1$d})", splitLen));
}

An example in IdeOne: http://ideone.com/rNlTj5

Solution 5 - Java

Late Entry.

Following is a succinct implementation using Java8 streams, a one liner:

String foobarspam = "foobarspam";
AtomicInteger splitCounter = new AtomicInteger(0);
Collection<String> splittedStrings = foobarspam
                                    .chars()
                                    .mapToObj(_char -> String.valueOf((char)_char))
                                    .collect(Collectors.groupingBy(stringChar -> splitCounter.getAndIncrement() / 3
                                                                ,Collectors.joining()))
                                    .values();

Output:

[foo, bar, spa, m]

Solution 6 - Java

This a late answer, but I am putting it out there anyway for any new programmers to see:

If you do not want to use regular expressions, and do not wish to rely on a third party library, you can use this method instead, which takes between 89920 and 100113 nanoseconds in a 2.80 GHz CPU (less than a millisecond). It's not as pretty as Simon Nickerson's example, but it works:

   /**
	 * Divides the given string into substrings each consisting of the provided
	 * length(s).
	 * 
	 * @param string
	 *            the string to split.
	 * @param defaultLength
	 *            the default length used for any extra substrings. If set to
	 *            <code>0</code>, the last substring will start at the sum of
	 *            <code>lengths</code> and end at the end of <code>string</code>.
	 * @param lengths
	 *            the lengths of each substring in order. If any substring is not
	 *            provided a length, it will use <code>defaultLength</code>.
	 * @return the array of strings computed by splitting this string into the given
	 *         substring lengths.
	 */
	public static String[] divideString(String string, int defaultLength, int... lengths) {
		java.util.ArrayList<String> parts = new java.util.ArrayList<String>();

		if (lengths.length == 0) {
			parts.add(string.substring(0, defaultLength));
			string = string.substring(defaultLength);
			while (string.length() > 0) {
				if (string.length() < defaultLength) {
					parts.add(string);
					break;
				}
				parts.add(string.substring(0, defaultLength));
				string = string.substring(defaultLength);
			}
		} else {
			for (int i = 0, temp; i < lengths.length; i++) {
				temp = lengths[i];
				if (string.length() < temp) {
					parts.add(string);
					break;
				}
				parts.add(string.substring(0, temp));
				string = string.substring(temp);
			}
			while (string.length() > 0) {
				if (string.length() < defaultLength || defaultLength <= 0) {
					parts.add(string);
					break;
				}
				parts.add(string.substring(0, defaultLength));
				string = string.substring(defaultLength);
			}
		}

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

Solution 7 - Java

Using plain java:

    String s = "1234567890";
    List<String> list = new Scanner(s).findAll("...").map(MatchResult::group).collect(Collectors.toList());
    System.out.printf("%s%n", list);

Produces the output: > [123, 456, 789]

Note that this discards leftover characters (0 in this case).

Solution 8 - Java

You can also split a string at every n-th character and put them each, in each index of a List :

Here I made a list of Strings named Sequence :

> List < String > Sequence

Then I'm basically splitting the String "KILOSO" by every 2 words. So 'KI' 'LO' 'SO' would be incorporate in separate index of the List called Sequence.

> String S = KILOSO >> Sequence = Arrays.asList(S.split("(?<=\G..)"));

So when I'm doing :

>System.out.print(Sequence)

It should print :

> [KI, LO, SO]

to verify I can write :

> System.out.print(Sequence.get(1))

it will print :

> LO

Solution 9 - Java

I recently encountered this issue, and here is the solution I came up with

final int LENGTH = 10;
String test = "Here is a very long description, it is going to be past 10";

Map<Integer,StringBuilder> stringBuilderMap = new HashMap<>();
for ( int i = 0; i < test.length(); i++ ) {
    int position = i / LENGTH; // i<10 then 0, 10<=i<19 then 1, 20<=i<30 then 2, etc.

    StringBuilder currentSb = stringBuilderMap.computeIfAbsent( position, pos -> new StringBuilder() ); // find sb, or create one if not present
    currentSb.append( test.charAt( i ) ); // add the current char to our sb
}

List<String> comments = stringBuilderMap.entrySet().stream()
        .sorted( Comparator.comparing( Map.Entry::getKey ) )
        .map( entrySet -> entrySet.getValue().toString() )
        .collect( Collectors.toList() );
//done



// here you can see the data
comments.forEach( cmt -> System.out.println( String.format( "'%s' ... length= %d", cmt, cmt.length() ) ) );
// PRINTS:
// 'Here is a ' ... length= 10
// 'very long ' ... length= 10
// 'descriptio' ... length= 10
// 'n, it is g' ... length= 10
// 'oing to be' ... length= 10
// ' past 10' ... length= 8

// make sure they are equal
String joinedString = String.join( "", comments );
System.out.println( "\nOriginal strings are equal " + joinedString.equals( test ) );
// PRINTS: Original strings are equal true

Solution 10 - Java

I'd start with something like

public List<String> split(String str, int interval) {
	if (str.length() <= interval) {
		return List.of(str);
	}
	var subStrings = new ArrayList<String>();
	int pointer = 0;
	while (str.length() > pointer) {
		String substring = str.substring(pointer, pointer + interval);
		subStrings.add(substring);
		pointer += interval;
	}
	return subStrings;
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionVijay DevView Question on Stackoverflow
Solution 1 - JavaBart KiersView Answer on Stackoverflow
Solution 2 - JavaKevin BourrillionView Answer on Stackoverflow
Solution 3 - JavaSimon NickersonView Answer on Stackoverflow
Solution 4 - JavaFrodoView Answer on Stackoverflow
Solution 5 - JavaPankaj SinghalView Answer on Stackoverflow
Solution 6 - JavaCardinal SystemView Answer on Stackoverflow
Solution 7 - JavavishalView Answer on Stackoverflow
Solution 8 - JavaVictor TruongView Answer on Stackoverflow
Solution 9 - JavaRobOhRobView Answer on Stackoverflow
Solution 10 - JavaSergey TsypanovView Answer on Stackoverflow