2

月、名前、合計でグループ化したいオブジェクトのコレクションがあります。

def things = [
    [id:1, name:"fred", total:10, date: "2012-01-01"],
    [id:2, name:"fred", total:10, date: "2012-01-03"],
    [id:3, name:"jane", total:10, date: "2012-01-04"],
    [id:4, name:"fred", total:10, date: "2012-02-11"],
    [id:5, name:"jane", total:10, date: "2012-01-01"],
    [id:6, name:"ted", total:10, date: "2012-03-21"],
    [id:7, name:"ted", total:10, date: "2012-02-09"]
];

出力を次のようにしたいと思います。

[
 "fred":[[total:20, month:"January"],[total:10, month:"February"]],
 "jane":[[total:20,month:"January"]],
 "ted" :[[total:10, month:"February"],[total:10, month:"March"]]
]

またはそれらの線に沿った何か。groovy/grails を使用してこれを達成する最良の方法は何ですか?

4

3 に答える 3

3

次の行

things.inject([:].withDefault { [:].withDefault { 0 } } ) { 
    map, v -> map[v.name][Date.parse('yyyy-MM-dd', v.date).format('MMMM')] += v.total; map 
}

この結果が得られます:

[fred:[January:20, February:10], jane:[January:20], ted:[March:10, February:10]]

(Groovy >= 1.8.7 および 2.0 で動作)

于 2012-11-08T20:36:58.087 に答える
1

私は

things.collect { 
  // get the map down to name, total and month
  it.subMap( ['name', 'total' ] ) << [ month: Date.parse( 'yyyy-MM-dd', it.date ).format( 'MMMM' ) ]
  // Then group by name first and month second
}.groupBy( { it.name }, { it.month } ).collectEntries { k, v ->
  // Then for the names, collect
  [ (k):v.collectEntries { k2, v2 ->
    // For each month, the sum of the totals
    [ (k2): v2.total.sum() ]
  } ]
}

アンドレと同じ結果を得るには、はるかに短く、はるかに良い答えです;-)

編集

少し短いですが、それでもそれほど良くはありません...

things.groupBy( { it.name }, { Date.parse( 'yyyy-MM-dd', it.date ).format( 'MMMM' ) } ).collectEntries { k, v ->
  [ (k):v.collectEntries { k2, v2 ->
    [ (k2): v2.total.sum() ]
  } ]
}
于 2012-11-08T20:39:28.617 に答える