Wednesday 12 August 2015

Unwrapping objects by an attribute in Groovy (also, flattening maps of maps)

Groovy truly is groovy, but sometimes you need to add in a little bit of sparkle to make it do what you want while not losing it's Groovy look.
It's easy to flatten a list of lists with Groovy: you just call flatten() on it: assert ["a", "b", ["ca", "cb", "cc"], ["da", ["dba", "dbb"], "dc"], "e"].flatten() == ["a", "b", "ca", "cb", "cc", "da", "dba", "dbb", "dc", "e"] Sometimes you might want to do something that is kind of what Groovy already offers you but it's not really quite there. Luckily Groovy offers you the ability to alter the behaviour of some methods, in this particular situation, you can pass a closure to flatten().
I wanted to flatten a list of objects by one of their attributes (while ignoring the parent object). Consider the example below where I want to unpack all boxes which contain boxes inside (i.e. child-boxes) in order to get a list of boxes that only have stuff inside (i.e. no child-boxes). def boxes = [ [ name: "Bigass Box of Boxes", childBoxes:[ [ name: "Box of Stuff", childBoxes:[] ], [ name: "Small Empty Box", childBoxes:[] ], [ name: "Medium Box of Boxes", childBoxes:[ [ name: "Box of books", childBoxes:[] ] ] ] ] ], [ name: "Another Empty Box", childBoxes:[] ] ] assert boxes.flatten({it.childBoxes.isEmpty() ? it : it.childBoxes}) == [[name:"Box of Stuff", childBoxes:[]], [name:"Small Empty Box", childBoxes:[]], [name:"Box of books", childBoxes:[]], [name:"Another Empty Box", childBoxes:[]]] This is particularly useful for unwrapping objects (e.g. unnesting nodes).

No comments:

Post a Comment