Splitting a string using a delimiter in Groovy and avoiding IndexOutOfBoundsException

11,213

Solution 1

You can use Groovy's multiple assignment feature to safely grab 3 values from the second tokenization. Consider following example:

def inputDetails = "1234-a0-12;1111-b0-34"

def cDesc = inputDetails.tokenize(";")

cDesc.each { part ->
    def (p1, p2, p3) = part.tokenize('-')

    println "DEBUG: Input details are, ${p1} : ${p2} : ${p3}"
}

Output:

DEBUG: Input details are, 1234 : a0 : 12
DEBUG: Input details are, 1111 : b0 : 34

The good thing is that this approach prevents IndexOutOfBoundsException or NullPointerException. If we change the first line to

def inputDetails = "1234-a0-12;1111-b0"

the result is:

DEBUG: Input details are, 1234 : a0 : 12
DEBUG: Input details are, 1111 : b0 : null

Solution 2

You can split the string into a 2D list by further splitting on '-':

def inputDetails = "1234-a0-12;1111-b0-34"
def elements = inputDetails.split(';').collect{it.split('-')}

elements is of type List<List<String>>. When printed, it yields:

[[1234, a0, 12], [1111, b0, 34]]

With this, you can afford more flexibility instead of hard-coding array indexes.

And with "1234-a0-12;1111-b0", it's split into [[1234, a0, 12], [1111, b0]]

Share:
11,213
Yash
Author by

Yash

Updated on July 30, 2022

Comments

  • Yash
    Yash over 1 year

    I want to split an input parameter inputDetails to unit level. I'm using tokenize for doing this. Here is my code:

    Groovy Code:

    def inputDetails = "1234-a0-12;1111-b0-34";
    def cDesc = inputDetails.tokenize(";");
    for (int i=0; i<cDesc.size(); ++i)
    {
        def cVer = cDesc.get(i);
        def cNum = cVer.tokenize("-");
        def a = cNum.get(0);
        def b = cNum.get(1);
        def c = cNum.get(2);
    
        println (" DEBUG : Input details are, ${a} : ${b} : ${c} \n");
    }
    

    Output:

     DEBUG : Input details are, 1234 : a0 : 12 
    
     DEBUG : Input details are, 1111 : b0 : 34
    

    This output is correct and expected. But if I change the first line of Groovy code to following:

    def inputDetails = "1234-a0-12;1111-b0";
    

    I get following error message:

     java.lang.IndexOutOfBoundsException: Index: 2, Size: 2
        at java_util_List$get$6.call(Unknown Source)
        at Script1.run(Script1.groovy:9)
    

    How can I fix it to prevent getting IndexOutOfBoundsException while supporting both, 1234-a0-12;1111-b0-34 and 1234-a0-12;1111-b0 inputs?

  • Yash
    Yash almost 6 years
    Hi Ernest, Your suggestion of splitting into a 2D array works but the result is an array form of my input: [[1234, a0, 12], [1111, b0, 34]]. I want to use each of the elements for a different purpose, how do i get 1234, a0, 12.. as seperate elements.
  • ernest_k
    ernest_k almost 6 years
    @Yash It's just a normal list of lists. You can just do a for-each: elements.each{list -> def a = list[0]; def b = list[1], }... and you can check the length of the list to know how many elements it contains.
  • Yash
    Yash almost 6 years
    Thanks for your help!
  • Yash
    Yash almost 6 years
    Thanks Szymon for making the problem statement more meaningful and the proposed solution.
  • Adam
    Adam over 5 years
    It's a missed opportunity that the original authors of groovy didn't decide on froody instead