Stupid Groovy Tricks

August 27th, 2008 by mgkimsal Leave a reply »

Someone recently asked how to get a random element from an array.  In PHP it’s pretty straightforward – array_rand($x) – but there’s not (AFAICT) a built-in way in Groovy to do this.  So I wrote a little something which should hopefully demonstrate the power of the metaClass stuff to boot.

ArrayList.metaClass.getRand = { number ->
 if(number==0) {
   return delegate[new Random().nextInt(delegate.size)]
 } else {
   def tempList = []
   def counter = 0
   while(counter>number) {
     tempList.add(delegate[new Random().nextInt(delegate.size)])
     counter++
   }
   return tempList
 }
}
def names = ['mike','matt','mark','lesley','jean','ron','jeff','martine']
println names.getRand()
println names.getRand(5)

The first call to getRand() on the names list will just return one name from the list.  The second will return 5 random entries (and some could theoretically be repeated).  I’ve added this getRand() method to the base ArrayList class at runtime, even though it’s likely declared ‘final’ in Java’s base libraries.  This is one of the core powers of Groovy, and is pretty slick, imo.

Share and Enjoy:
  • del.icio.us
  • DZone
  • Facebook
  • Reddit
  • StumbleUpon
  • Digg
  • Simpy
  • Technorati
Advertisement

5 comments

  1. mgkimsal says:

    BTW, this was a first pass. If there’s any way of making this groovier, let me know!

  2. Bob says:

    Consider the following if you want to prevent duplicates in the else branch. It will be slower in general since it will shuffle the entire list.

    def tempList= new ArrayList(delegate)
    Collections.shuffle(tempList)
    tempList.subList(0, length)
    return tempList

    This might useful if you a supply a third boolean argument to the closure that indicates whether duplicates should be allowed or not.

    Nice post!

  3. Bob says:

    That should be

    return tempList.subList(0, length)

  4. Burke says:

    Even Groovier…

    ArrayList.metaClass.getRand = { number ->
      (0..<(number?:1)).collect{delegate[new Random().nextInt(delegate.size())]}
    } 
    def names = ['mike','matt','mark','lesley','jean','ron','jeff','martine']
    println names.getRand()
    println names.getRand(5)
  5. Krystian says:

    Hi,

    if you are publishing code samples, could you please at least test it?
    People are googling for some ideas and they try to use code from the web thinking: if it’s published someone tested it!
    Line 2:
    if(number==0) {

    You are missing a check for number == null. Without it this line:
    println names.getRand()

    will never work.

    Then you have an endless loop:

    def counter = 0
    while(counter>number) {

    Your idea is great, Burke’s implementation is awesome, but the code snippet in your post makes me angry enough to write this post ;)

    Sorry for the rant, having a bad day I guess.

Leave a Reply