How to convert a 2d array to 3d array dynamically in groovy

Viewed 119

How can we convert a 2d array to 3d dynamically.I am having below input and i'm splitting using closure for 2d array but how can we convert to 3d array by splitting based on #.

def input = '''123456789#987465321,7410258#9630
852014864#456486454,5454646#4454''';

input=input.split('\n').collect{it.split(',')}

I tried to split like below code, But I'm getting exception. Is there any way using closure or any other method where we can split dynamically iresspective of input dimension in groovy.

input=input.collect{it.split('#')};

Caught: groovy.lang.MissingMethodException: No signature of method: [Ljava.lang.String;.split() is applicable for argument types: (java.lang.String) values: [#]
Possible solutions: split(groovy.lang.Closure), wait(), sort(), init(), toList(), tail()
groovy.lang.MissingMethodException: No signature of method: [Ljava.lang.String;.split() is applicable for argument types: (java.lang.String) values: [#]
Possible solutions: split(groovy.lang.Closure), wait(), sort(), init(), toList(), tail()
    at com.test.TextScript$_run_closure2.doCall(TextScript.groovy:10)
    at com.test.TextScript.run(TextScript.groovy:10)

SO, I wanted to create a method in groovy which will take input parameter and the splitting delimiter which will create multidemensional array dynamically.

Example:

    static def split(def input,def delimiter){
    .
    .
    .
    }

def input = '''123456789#987465321,7410258#9630
852014864#456486454,5454646#4454'''; 
def result1=split(input,'\n');
println result1//1d [123456789#987465321,7410258#9630, 852014864#456486454,5454646#4454]

def result2=split(result1,',');
println result2//2d [[123456789#987465321, 7410258#9630], [852014864#456486454, 5454646#4454]]

def result3=split(result2,'#');
println result3// three dimension[[[123456789],[987465321], [7410258],[9630]], [[852014864],[456486454], [5454646],[4454]]]
2 Answers

It's not really clear what format you want the data in. This will take you closer to a solution:

def input = '''123456789#987465321,7410258#9630
852014864#456486454,5454646#4454'''

input.readLines().each { line ->
    println line.split(/,|#/)
}

Prints:

[123456789, 987465321, 7410258, 9630]
[852014864, 456486454, 5454646, 4454]

If you want it in a data structure, consider a map:

Map m = [:]
input.readLines().each { line ->
    line.split(/,/).each { kv ->
        List pairs = kv.split(/#/)
        m.put(pairs[0], pairs[1])
    }
}

println m

Produces:

[123456789:987465321, 7410258:9630, 852014864:456486454, 5454646:4454]

EDIT:

After understanding your expected output better, I think this is close to what you want, if not it will help you develop what you want.

import java.util.Collections

List li = []
input.readLines().each { line ->
    line.split(/,/).each { kv ->
        li.add(kv)
        li.each {
            Collections.replaceAll(li, kv, []+kv.split(/#/))
        }
    }
}

println li

It outputs:

[[[123456789, 987465321]], [[7410258, 9630]], [[852014864, 456486454]], [[5454646, 4454]]]

You should be able to wrap it in a method and parameterise it yourself.

You can do this with a recursive function. Pass in the initial input, you want to split and a list of regexp. In each step the next split will be done with the regexp for the depth. E.g.

def multiSplit(String input, List res) {
  def result = input.split(res.head())
  res.size()>1 ? result.collect{ multiSplit(it, res.tail()) } : result
}

println(multiSplit('''123456789#987465321,7410258#9630
852014864#456486454,5454646#4454''', ["\n", ",", "#"]))
// → [[[123456789, 987465321], [7410258, 9630]], [[852014864, 456486454], [5454646, 4454]]]
Related