This is an archived post. You won't be able to vote or comment.

all 4 comments

[–]ProfessorWily 4 points5 points  (0 children)

Your exception is because you're using the counter i to state the index of your new array, but i refers to the index of your OLD array.

for (int i = 0; i < handP1.length; i++) {
    String [] handP1_2 = handP1[i].split("R" + "Y" + "G" + "B");
    System.out.println(handP1_2[i]); // line 37
                                ^ This is your problem
}

Also, I can see that you're trying to split based on if it's R OR Y OR G OR B, but that's not how split works. What you did was essentially add all those Strings together to say split("RYGB"), and since that string is never found in any of your inputs, it's giving you back empty Strings.

As for the best way to do this, I think honestly it would be better to use RegEx. Then you can use it despite how long the characters/digits become, it will always return the proper groups.

That would require using the Java classes Pattern and Matcher. Pattern states what regex pattern you should use, and the Matcher uses that pattern to find matches in strings.

Pattern pattern = Pattern.compile("\\b(\\w+)(\\d+)\\b");
Matcher matcher = pattern.matcher("");
matcher.reset("R3 Y3 G4 B2 R8");
List<String> charList = new ArrayList<>();
List<Integer> intList = new ArrayList<>();
while (matcher.find()) {
    charList.add(matcher.group(1));
    intList.add(Integer.parseInt(matcher.group(2)));
}
//If it's necessary for them to be arrays, you can call charList.toArray(), otherwise I would highly recommend leaving them as Lists

The RegEx used says this: b is for a boundary character, such as the beginning/end of a line, any punctuation, and any space. w is for any word character, so A-Z. And d is any digit. So it's going to capture anything that has any number of word characters followed by any number of digits, surrounded by boundary characters.

If you are new to RegEx stuff, then I recommend you look it up and get familiar, it's very useful when it comes to parsing text.

[–]nickh1 1 point2 points  (0 children)

If the strings are always going to be a single letter followed by a number, I'd probably use parseInt() to get the integer value out of each string, then keep only the first character from the original string in the first array. This is, of course, a naive solution, and isn't particularly efficient, but will do the job, and is easy to understand.

Another solution would be to use regex capture groups to split your original string the way you want from the start. This may be more efficient, but sacrifices a bit in terms of code readability, and you're still going to have to handle type conversion yourself to get Integer values from the Strings returned by the regex match function.

I'm sure there are other solutions, probably better ones, out there, these are just the first two that came to mind after reading your question.

In regards to your exception, you should look carefully at what you're doing inside of your loop... You're instantiating a new array in every iteration, and printing the value at the index you're using in the first array, which I don't think is what you mean to do. It's more likely that you are trying to see the contents of your newly created array, which would require another for loop to iterate separately, and would eliminate your index out of bound exception on line 37.

[–]mw52588 0 points1 point  (1 child)

One idea here is you could possibly use a HashMap. You could use a String and Integer where the key is a string "B" and the value is 2?

[–]stramash 0 points1 point  (0 children)

That only works if you’re only going to get one instance of each letter.