Reputation: 35
I am trying to use the Groovy groupBy and max methods to summarise data in my list.
So far I have created a class named allowance which I use to build a list of allowances e.g.
class allowance {
Integer StartDate
Integer EndDate
String PayCode
Integer CreatedOn
}
def lAllowances = [
new allowance(StartDate: 20200330, EndDate: 99991231, PayCode: "PC_DFB1", CreatedOn: 20200330)
,new allowance(StartDate: 20200330, EndDate: 99991231, PayCode: "PC_DFB1", CreatedOn: 20200420)
,new allowance(StartDate: 20180405, EndDate: 20200329, PayCode: "PC_DFB1", CreatedOn: 20180125)
,new allowance(StartDate: 20200330, EndDate: 99991231, PayCode: "PC_DFB2", CreatedOn: 20200330)
,new allowance(StartDate: 20100405, EndDate: 99991231, PayCode: "PC_CAR1", CreatedOn: 20100103)
]
I now need to group this list and return the latest created allowance based upon CreatedOn for the grouping key (PayCode, StartDate).
I can get it to return what I need with one groupBy closure e.g.
lAllowances.groupBy {it.PayCode}.collectEntries {[(it.key): it.value.max {it.CreatedOn}]}.each{ k,v ->
mAllowances.put (iCount, [StartDate: v.StartDate, EndDate: v.EndDate, PayCode: k])
iCount++
}
but when I specify a second closure the max method doesn't seem to work or at least it doesn't return what I thought it would e.g.
lAllowances.groupBy ({it.PayCode},{it.StartDate}).collectEntries {[(it.key): it.value.max {it.CreatedOn}]}.each{ k,v ->
mAllowances.put (iCount, [StartDate: v.StartDate, EndDate: v.EndDate, PayCode: k])
iCount++
}
The expected result set after grouping based upon the data above would be something like:
PayCode: "PC_DFB1", StartDate: 20200330, EndDate: 99991231, CreatedOn: 20200420
PayCode: "PC_DFB1", StartDate: 20180405, EndDate: 20200329, CreatedOn: 20180125
PayCode: "PC_DFB2", StartDate: 20200330, EndDate: 99991231, CreatedOn: 20200330
PayCode: "PC_CAR1", StartDate: 20100405, EndDate: 99991231, CreatedOn: 20100103
Any help you can give to resolve this would be greatly appreciated.
Thanks!
Upvotes: 1
Views: 262
Reputation: 672
You can concatenate the fields to group by, and then collect with the max closure for each of the matches
def result = lAllowances.groupBy { it.StartDate + it.PayCode }
.collect { def matchKey, def matches ->
return matches.max { it.CreatedOn }
}
this returns your described result.
If there is a risk of the concatenation creating false matches (e.g 1 + 11
and 11 + 1
), you can insert a separator character like |
in between.
Upvotes: 1