shortcut for creating a Map from a List in groovy?

I've recently came across the need to do exactly that: converting a list into a map. This question was posted before Groovy version 1.7.9 came out, so the method collectEntries didn't exist yet. It works exactly as the collectMap method that was proposed:

Map rowToMap(row) {
    row.columns.collectEntries{[it.name, it.val]}
}

If for some reason you are stuck with an older Groovy version, the inject method can also be used (as proposed here). This is a slightly modified version that takes only one expression inside the closure (just for the sake of character saving!):

Map rowToMap(row) {
    row.columns.inject([:]) {map, col -> map << [(col.name): col.val]}
}

The + operator can also be used instead of the <<.


Check out "inject". Real functional programming wonks call it "fold".

columns.inject([:]) { memo, entry ->
    memo[entry.name] = entry.val
    return memo
}

And, while you're at it, you probably want to define methods as Categories instead of right on the metaClass. That way, you can define it once for all Collections:

class PropertyMapCategory {
    static Map mapProperty(Collection c, String keyParam, String valParam) {
        return c.inject([:]) { memo, entry ->
            memo[entry[keyParam]] = entry[valParam]
            return memo
        }
    }
}

Example usage:

use(PropertyMapCategory) {
    println columns.mapProperty('name', 'val')
}

Was the groupBy method not available when this question was asked?


If what you need is a simple key-value pair, then the method collectEntries should suffice. For example

def names = ['Foo', 'Bar']
def firstAlphabetVsName = names.collectEntries {[it.charAt(0), it]} // [F:Foo, B:Bar]

But if you want a structure similar to a Multimap, in which there are multiple values per key, then you'd want to use the groupBy method

def names = ['Foo', 'Bar', 'Fooey']
def firstAlphabetVsNames = names.groupBy { it.charAt(0) } // [F:[Foo, Fooey], B:[Bar]]

Also, if you're use google collections (http://code.google.com/p/google-collections/), you can do something like this:

  map = Maps.uniqueIndex(list, Functions.identity());