Groovy iterate in arraylist, find indexes with same fields

Viewed 51

I have a class defined like this:

class someData{
def name
def type
def minVal}

I'm reading all this related data from an excel file to an arraylist by doing

def dataHolder = new ArrayList()

dataHolder.add(new someData(
name: "",
type:"",
minVal:""
))

"" lines are actually filled with datas split by "," from my excel file.

Now let's say I have a ArrayList like this in the end:

dataHolder[0]--> name: name1, type:int, minVal:8
dataHolder[1]--> name: name2, type:int, minVal:11
dataHolder[2]--> name: name3, type:int, minVal:8
dataHolder[3]--> name: name4, type:uint32, minVal:8
dataHolder[4]--> name: name4, type:double, minVal:155
dataHolder[5]--> name: name4, type:float, minVal:48
dataHolder[6]--> name: name5, type:long, minVal:2855

What I want to do is iterate through this ArrayList, if name at index [i] is different than index [i+1] add this one to another ArrayList(with its name,type & minVal). If name remains same add it to my new ArrayList's next index but fill its fields too.

To be more clear, I want to have something like this in the end:

newArrList[0]--> name: name1, type:int, minVal:8
newArrList[1]--> name: name2, type:int, minVal:11
newArrList[2]--> name: name3, type:int, minVal:8
newArrList[3]--> name: name4, type:uint32,double,float minVal:8,155,48
newArrList[4]--> name: name5, type:long, minVal:2855

I cannot change the code too much but at most I can change the class to

class someData{
def name = new ArrayList()
def type = new ArrayList()
def minVal = new ArrayList()
}

All help is appreciated.

1 Answers

So given your example holder class (with an annotation to make it print out nicely):

@groovy.transform.ToString
class SomeData {
    def name
    def type
    def minVal
}

You can create your example input like so:

def input = [
    new SomeData(name: 'name1', type: 'int', minVal: 8),
    new SomeData(name: 'name2', type: 'int', minVal: 11),
    new SomeData(name: 'name3', type: 'int', minVal: 8),
    new SomeData(name: 'name4', type: 'uint32', minVal: 8),
    new SomeData(name: 'name4', type: 'double', minVal: 155),
    new SomeData(name: 'name4', type: 'float', minVal: 48),
    new SomeData(name: 'name5', type: 'long', minVal: 2855),
]

Then _assuming the names are always in order`, to get the answer you say you want, you can do this:

def result = input.groupBy { it.name }.collect { name, data ->
    if (data.size() > 1) {
        new SomeData(name: name, type: data.type, minVal: data.minVal)
    } else {
        new SomeData(name: name, type: data.type.head(), minVal: data.minVal.head())
    }
}

As can be seen by printing them out:

result.each {
    println it
}

output:

SomeData(name1, int, 8)
SomeData(name2, int, 11)
SomeData(name3, int, 8)
SomeData(name4, [uint32, double, float], [8, 155, 48])
SomeData(name5, long, 2855)

It may be simpler for further processing to just keep single item results in a list (as with name4)

In that case, you can simplify to

def result = input.groupBy { it.name }.collect { name, data ->
    new SomeData(name: name, type: data.type, minVal: data.minVal)
}

Which gives us:

SomeData(name1, [int], [8])
SomeData(name2, [int], [11])
SomeData(name3, [int], [8])
SomeData(name4, [uint32, double, float], [8, 155, 48])
SomeData(name5, [long], [2855])
Related