Groovy Collection method: groupBy()

06 / Apr / 2009 by Aman Aggarwal 7 comments

public Map groupBy(Closure closure)

Going through Groovy Collection, I found this powerful method which takes a Closure as parameter & based on the closure, it returns a map in which all unique values returned by closure act as keys.

Lets take an example:

If you want to group integers between 1 to 100 based on the integer value at units place as follows:

[1:[1, 11, 21, 31, 41, 51, 61, 71, 81, 91],
2:[2, 12, 22, 32, 42, 52, 62, 72, 82, 92],
3:[3, 13, 23, 33, 43, 53, 63, 73, 83, 93],
4:[4, 14, 24, 34, 44, 54, 64, 74, 84, 94],
5:[5, 15, 25, 35, 45, 55, 65, 75, 85, 95],
6:[6, 16, 26, 36, 46, 56, 66, 76, 86, 96],
7:[7, 17, 27, 37, 47, 57, 67, 77, 87, 97],
8:[8, 18, 28, 38, 48, 58, 68, 78, 88, 98],
9:[9, 19, 29, 39, 49, 59, 69, 79, 89, 99],
0:[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]]

Just think of the code you will need to write in Java for this.

However, its a single method call in Groovy: (1..100).groupBy{it%10}

Hope to find more such methods over time.


~Aman Aggarwal
aman@intelligrape.com

http://www.IntelliGrape.com/

FOUND THIS USEFUL? SHARE IT

Tag -

Grails Groovy

comments (7)

  1. Matt Passell

    Thanks for the tip! There are a lot of great methods added to Collection by Groovy.

    I recently blogged about the min() and max() methods
    For example, if you want to find the most recently modified file in a directory (dir), this is all you need:

    def newestFile =
    dir.listFiles().max{ it.lastModified() }

    Reply
  2. Alexander Malfait

    Maybe a more use case as requested above:

    Map invoicesPerClient = invoices.groupBy{ it.client }

    invoicesPerClient.each { client, invoices ->
    println client.name + ” has ” + invoices.length + ” invoices”
    }

    Reply
  3. Bernard Giusiano

    // An other example of groupBy :
    // Count the number of items and display them for each creator of more than 2 posts in RSS feeds
    // Bernard Giusiano – 08/04/09
    Locale.setDefault Locale.ENGLISH // if your computer don’t speak english
    rssFeed = “http://feeds2.feedburner.com/groovyblogs”.toURL().text // my prefered Groovy RSS
    rssXML = new XmlSlurper().parseText(rssFeed) // get data
    // transform rssXML into a table (list of maps)
    rssTable = rssXML.channel.item.inject([]) { allItems, eachItem ->
    allItems <
    record += [(element.name()):(element.toString())]
    }
    }
    // group by creator
    groupedByCreator = rssTable.groupBy { it.creator }
    // select creators who have posted more than two times
    moreThanTwo = groupedByCreator.findAll { group -> group.value.size() > 2 }
    // display what you want from each group
    moreThanTwo.each { group ->
    println group.key.padRight(70,’.’) + group.value.size() + ‘ items’
    group.value.each { post ->
    println ” ${Date.parse(‘EEE, d MMM yyyy HH:mm:ss Z’,post.pubDate).format(‘dd/MM/yy’)} : ${post.title} (${post.link})”
    }
    }
    return null // to stop display of big result in GroovyConsole

    Reply
  4. Egon

    Is this a more realistic use case?

    [ ‘Java’, ‘Groovy’, ‘JavaScript’, ‘Smalltalk’ ].groupBy { it[0] }

    It sorts the languages by their first letter:

    [J:[Java, JavaScript], G:[Groovy], S:[Smalltalk]]

    Reply
  5. bhagwat

    really a powerful method. thanx 4 sharing such valuable info… it will be more helpful if u give more realistic use case to use such a method.

    Reply

Leave a Reply to Matt Passell Cancel reply

Your email address will not be published. Required fields are marked *