Groovy:GroupBy并获取具有最大日期的对象

时间:2018-08-09 10:50:39

标签: groovy

如何从对象列表中按字段ts分组并以最大startDate分组来获取新列表?

def list = [
  new Timeserie(ts:11, startDate:new Date().parse('yyyy-MM-dd HH:mm:ss', '2018-02-12 20:04:36')),
  new Timeserie(ts:11, startDate:new Date().parse('yyyy-MM-dd HH:mm:ss', '2018-02-12 20:14:36')),
  new Timeserie(ts:12, startDate:new Date().parse('yyyy-MM-dd HH:mm:ss', '2018-02-12 20:24:36')),
  new Timeserie(ts:12, startDate:new Date().parse('yyyy-MM-dd HH:mm:ss', '2018-02-12 20:34:36')),
]

list.each{ println it }             
def byTs = list.groupBy({ tss -> tss.ts })          
println "byTs Size: " + byTs.size()

预期结果:

[new Timeserie(ts:11, startDate:new Date().parse('yyyy-MM-dd HH:mm:ss', '2018-02-12 20:14:36'),
new Timeserie(ts:12, startDate:new Date().parse('yyyy-MM-dd HH:mm:ss', '2018-02-12 20:34:36'))]

2 个答案:

答案 0 :(得分:0)

您可以通过链接进行3项操作来获得预期的结果:

  • groupBy { it.ts }创建一个映射,其中键为ts,值为时间序列列表Map<Integer, List<Timeserie>>
  • collectEntries { [(it.key): it.value.max { it.startDate }] }Map<Integer, List<Timeserie>>转换为Map<Integer, Timeserie>,其中映射对象是最高startDate的时间序列
  • values()Collection<Timeserie>获得Map<Integer, Timeserie>

完整的示例如下:

def list = [
  new Timeserie(ts:11, startDate:new Date().parse('yyyy-MM-dd HH:mm:ss', '2018-02-12 20:04:36')),
  new Timeserie(ts:11, startDate:new Date().parse('yyyy-MM-dd HH:mm:ss', '2018-02-12 20:14:36')),
  new Timeserie(ts:12, startDate:new Date().parse('yyyy-MM-dd HH:mm:ss', '2018-02-12 20:24:36')),
  new Timeserie(ts:12, startDate:new Date().parse('yyyy-MM-dd HH:mm:ss', '2018-02-12 20:34:36')),
]

def result =  list.groupBy { it.ts }
  .collectEntries { [(it.key): it.value.max { it.startDate }] }
  .values()

println result

输出:

[Timeserie(11, Mon Feb 12 20:14:36 CET 2018), Timeserie(12, Mon Feb 12 20:34:36 CET 2018)]

答案 1 :(得分:0)

我会用withDefault()来解决问题:

def list = [  [ts:11, startDate:new Date().parse('yyyy-MM-dd HH:mm:ss', '2018-02-12 20:04:36')],   [ts:11, startDate:new Date().parse('yyyy-MM-dd HH:mm:ss', '2018-02-12 20:14:36')],  [ts:12, startDate:new Date().parse('yyyy-MM-dd HH:mm:ss', '2018-02-12 20:24:36')],  [ts:12, startDate:new Date().parse('yyyy-MM-dd HH:mm:ss', '2018-02-12 20:34:36')], ]

def res = list.inject( [:].withDefault{ [ ts:null, startDate:new Date( 0 ) ] } ){ res, ts ->
  res[ ts.ts ].ts = ts.ts
  res[ ts.ts ].startDate = new Date( Math.max( ts.startDate.time, res[ ts.ts ].startDate.time ) )
  res
}.values()

assert '[[ts:11, startDate:Mon Feb 12 20:14:36 UTC 2018], [ts:12, startDate:Mon Feb 12 20:34:36 UTC 2018]]' == res.toString()

注意:为简单起见,我将Timeserie类替换为Map