3

I want to split a string in 2 characters without any delimiter, but Regex split is not working properly

here is my code:-

  String str="splitstring";
    System.out.println("Split.."+str.trim().split("(?<=\\G.{2})").length);
    System.out.println("Split.."+str.trim().split("(?<=\\G.{2})")[0]);
    System.out.println("Split.."+str.trim().split("(?<=\\G.{2})")[1]);

output:-

 Split..2

 Split..sp

 Split..litstring
FD_
  • 12,947
  • 4
  • 35
  • 62
Ankit Mahadik
  • 2,275
  • 22
  • 35
  • 2
    What is your expected output? – Yassin Hajaj Mar 16 '16 at 08:18
  • my expected output is array of split string with 2 character and on each position 2 character available like.on position 0 it will return "sp" than on position 1 return "li" than on 2 position "ts" up to end of string – Ankit Mahadik Mar 16 '16 at 08:22
  • 1
    This must be a glitch in the ICU regex library. – Wiktor Stribiżew Mar 16 '16 at 08:34
  • @WiktorStribiżew I think you're indeed right that this is a bug, since the following `System.out.println(Arrays.toString(str.split("(?<=\\G.{2})")));` gives the expected behavior.. – Kevin Cruijssen Mar 16 '16 at 08:59
  • @KevinCruijssen: I start thinking that the `\G` behavior inside a lookbehind is undefined. Here is a [PHP demo](https://ideone.com/sVJ3tt) (`[0] => sp, [1] => lit, [2] => str, [3] => ing, [4] => `), [C# demo](http://ideone.com/h72qZT) (same as Java output), [Ruby demo](https://ideone.com/lTUdXz) (same as Java output). [R (that also uses a PCRE engine!) example works as in Java, too](https://ideone.com/XRU9ai). – Wiktor Stribiżew Mar 16 '16 at 09:08
  • my code also run perfect in java but when i implemented this code in android than its not working properly – Ankit Mahadik Mar 16 '16 at 11:20

3 Answers3

1

Looks like it's a bug with the result threshold limit in your Java environment. Try to workaround it by providing the limit explicitly:

    String str="splitstring";
    int partsCount = (str.length() + 1) / 2;
    System.out.println("Split.."+str.trim().split("(?<=\\G.{2})", partsCount).length);
    System.out.println("Split.."+str.trim().split("(?<=\\G.{2})", partsCount)[0]);
    System.out.println("Split.."+str.trim().split("(?<=\\G.{2})", partsCount)[1]);
amukhachov
  • 5,822
  • 1
  • 41
  • 60
0

I assume you want to divide string into two equal halves, substrings.. Then this might help !!

System.out.println("Split.."+str.trim().split("(?=\\D)")[0]);
pavanjoshi
  • 240
  • 2
  • 10
0

Why do you use a regex for this?

You can do something like this:

String str = "splitstring";
System.out.println("String-length: " + str.length());
for (int i = 0; i < str.length(); i += 2) { // Increments of 2
  System.out.print("Split.." + str.charAt(i));
  if (i != str.length() - 1) {
    System.out.print(str.charAt(i + 1));
  }
  System.out.println();
}

Output:

String-length: 11
Split..sp
Split..li
Split..ts
Split..tr
Split..in
Split..g

EDIT: If you insist of using the regex though, here it is:

final String str = "splitstring";
System.out.println(Arrays.toString(
    str.split("(?<=\\G.{2})")
));

Output remains the same as above. Seems like there is indeed a bug or something, since the regex is the same as in your question.. Can't really say for sure though, since it's not really my expertise.


EDIT 2: Jon Skeet has an alternative method that is more efficient than mine above:

Well, it's fairly easy to do this by brute force:

public static List<String> splitEqually(String text, int size) {
    // Give the list the right capacity to start with. You could use an array
    // instead if you wanted.
    List<String> ret = new ArrayList<String>((text.length() + size - 1) / size);

    for (int start = 0; start < text.length(); start += size) {
        ret.add(text.substring(start, Math.min(text.length(), start + size)));
    }
    return ret;
}

I don't think it's really worth using a regex for this.

EDIT: My reasoning for not using a regex:

  • This doesn't use any of the real pattern matching of regexes. It's just counting.
  • I suspect the above will be more efficient, although in most cases it won't matter
  • If you need to use variable sizes in different places, you've either got repetition or a helper function to build the regex itself based on a parameter - ick.
  • The regex provided in another answer firstly didn't compile (invalid escaping), and then didn't work. My code worked first time. That's more a testament to the usability of regexes vs plain code, IMO.
Community
  • 1
  • 1
Kevin Cruijssen
  • 9,153
  • 9
  • 61
  • 135
  • 1
    *Why do you use a regex for this?* - Compare how many lines of code you had to write. With regex, it is a one-liner. – Wiktor Stribiżew Mar 16 '16 at 08:47
  • @WiktorStribiżew Can be, but this can be put in a method and hidden somewhere out of sight. Personally I think people tend to use regex too soon, while a lot of times it can be done perfectly without. Anyway, I've made an edit to have the same result with the regex.. – Kevin Cruijssen Mar 16 '16 at 08:57
  • Some consider the *put in a method and hidden somewhere out of sight* an advantage. BTW, the regex solution you suggest is the one that does not work for OP on Android. Note that Android uses an ICU regex library, different from what is used in Java. – Wiktor Stribiżew Mar 16 '16 at 08:59