0

I want to convert a string to an array of substrings based on the length of the substrings. is there any solution without using a loop? for example:

"this is a test" -> ["thi","s i","s a"," te","st"]

Update:

more solutions here: Splitting a string at every n-th character

pesehr
  • 787
  • 2
  • 9
  • 23
  • 1
    Your substrings are not of equal length. see the last one "st" is of length 2 as others are of length 3. – Priya Jain Jan 31 '18 at 19:30
  • 1
    The question is unclear - what would be an accepted output? Based on what condition? – zlakad Jan 31 '18 at 19:32
  • @PriyaJain I know cause the length of the string is not dividable by 3. – pesehr Jan 31 '18 at 19:35
  • @zlakad take looks at the example. the input string has been divided into the array of the substring with length 3. – pesehr Jan 31 '18 at 19:38
  • 1
    O.K. now IS clear! If you want to use regex, you should accept @Cardinal System answer. But, if you don't want to use regex, let us know... – zlakad Jan 31 '18 at 19:41

1 Answers1

3

Look at Bart Kiers' example:

System.out.println(java.util.Arrays.toString("this is a test".split("(?<=\\G...)")));

The number of periods '.' indicates how many characters each sub string will be.


EDIT

As Mick Mnemonic pointed out, you can also use Kevin Bourrillion's example:

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.

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):

   /**
     * 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()]);
    }
Cardinal System
  • 2,749
  • 3
  • 21
  • 42
  • Frankly, I would never use a cryptic regex such as this one in production code. [Kevin's answer to the same question](https://stackoverflow.com/a/2298477/905488) shows how using a good utility library gets the job done succinctly and readably: `Splitter.fixedLength(3).split(string);` – Mick Mnemonic Jan 31 '18 at 19:55
  • @MickMnemonic It should be no problem if you create a wrapper function with a clear name instead of importing a whole library for one specific feature. – m0skit0 Jan 31 '18 at 19:59
  • Guava should be a standard import in any non-trivial project, not just for string splitting. – Mick Mnemonic Jan 31 '18 at 20:05
  • 1
    @MickMnemonic That's a subjective opinion though. – m0skit0 Feb 01 '18 at 10:14
  • @MickMnemonic I'm curious, why do you not use regex such as this? Also, I provided an example that does not use regex nor does it rely on third party libraries, so that at least pleases m0skit0. – Cardinal System Feb 01 '18 at 22:09
  • @CardinalSystem, primarily, I wouldn't use it because of readability and maintainability. Your average maintenance programmer doesn't have an idea what the syntax means and how to change it, if need be. If the project already includes a utility library such as Guava, it would be a no-brainer to use an existing utility method for this instead of re-implementing it (using imperative syntax or a regex). Every line of code in your codebase needs to be maintained so you don't want to implement tasks like this yourself. – Mick Mnemonic Feb 02 '18 at 04:04