Monday, October 1, 2012

Groovy tricks: initializing map with array values by default

I feel a little Mr. Haki today, so will post Groovy recipe.
Very often, there is case when you want to aggregate some values by single key, but groupBy is not suitable or flexible enough. In this case, with every new key, you should initialize this new value with array, like:


Map values = [:]
[[key:'user1', val:123],[key:'user1', val:567],[key:'user2', val:999]].each {
  def var = values[it.key]
  if (!var) {
    var = []
    values[it.key] = var
  }
  var << it.val
}
println values

[user1:[123, 567], user2:[999]]

This is nice, but "if" statement looks redundant and ugly and complicates things. Fortunately, there is great Groovy method called "withDefault" which does pretty much same things, but in much groovier way: if there is no key, instead of null it assigns specified value to your key. So above example can be rewritten like:


Map values = [:].withDefault {k->[]}
[[key:'user1', val:123],[key:'user1', val:567],[key:'user2', val:999]].each {
  values[it.key] << it.val
}
println values
[user1:[123, 567], user2:[999]]

No comments:

Post a Comment