rny7
rny7

Reputation: 13

Groovy/Grails groupBy dynamic list of fieldnames

i want to group a list of objects by a dynamic list of fields (given by name). I'll try to explain it with an example.

Let's say I have a class looking similar to this:

def SomeClass{
    String one
    String two
    String three
    String four
    //etc..
}  

Now I have a changeable list of 1-4 field names, therefore hardcoding is not an option, like this:

def fields = ["one", "two"]
//or
def fields2 = ["two", "three", "four"]

I want to sort lists of SomeClass, and as result I need a map with a list of values as key and the objects as value; Looking like this:

//group by fields:
def result = [[someClass.one, someClass.two]:[List<SomeClass>],...]
//group by fields2:
def result2 = [[someClass.two, someClass.three, someClass.four]:[List<SomeClass>],...]

I tried splitting the fields and create closures for .groupBy(), but I retrieve a nested Map.

With .collectEntries() i'm not sure how to pass a changeable list of fields to the closure.

The lists I want to sort contain around 500-10000 elements, with 1-4 fields I want to group by.

Upvotes: 1

Views: 704

Answers (1)

tim_yates
tim_yates

Reputation: 171084

You can use groupBy with a Closure and collect your fields inside it:

import groovy.transform.*

@Canonical
class SomeClass{
    String one
    String two
    String three
} 

List<SomeClass> list = [
    new SomeClass('a', '1', 'i'),
    new SomeClass('a', '1', 'ii'),
    new SomeClass('a', '2', 'i'),
    new SomeClass('a', '2', 'ii'),
    new SomeClass('a', '3', 'i'),
]

def fields = ['one', 'two']

Map<List<String>,List<SomeClass>> grouped = list.groupBy { o -> fields.collect { o."$it" } }

assert grouped == [
    ['a', '1']:[new SomeClass('a', '1', 'i'), new SomeClass('a', '1', 'ii')],
    ['a', '2']:[new SomeClass('a', '2', 'i'), new SomeClass('a', '2', 'ii')],
    ['a', '3']:[new SomeClass('a', '3', 'i')]
]

Upvotes: 2

Related Questions