tags:

views:

1374

answers:

4

Hi, I have a groovy list of lists i.e.

list = [[2, 0, 1], [1, 5, 2], [1, 0, 3]]

I would like sort it by order of the first element, then second, then third.

Expected

assert list == [[1, 0, 3], [1, 5, 2], [2, 0, 1]]

I started with list = list.sort{ a,b -> a[0] <=> b[0] } but that only sorts the first element. How do you finish?

Thanks

A: 

Here's what I came up with, not the most groovy way I suppose..

list = list.sort{ a,b -> 
    if(a[0].compareTo(b[0]) == 0) {
     if(a[1].compareTo(b[1]) == 0) {
      return a[2].compareTo(b[2]);
     } else {
      return a[1].compareTo(b[1]);
     }
    } else {
     return a[0].compareTo(b[0]);
    }
}
Ying
+2  A: 

You should just be able to iterate through the sorts in reverse precedence:

list = [[2, 0, 1], [1, 5, 2], [1, 0, 3]]

list = list.sort{ a,b -> a[2] <=> b[2] }
list = list.sort{ a,b -> a[1] <=> b[1] }
list = list.sort{ a,b -> a[0] <=> b[0] }

assert list == [[1, 0, 3], [1, 5, 2], [2, 0, 1]]

It should establish sorting within the lower precedence and reorder it just enough for upper.


Edit -- If Groovy supports it, a better option would actually be:

list.sort{ a,b -> (a[0] <=> b[0]) || (a[1] <=> b[1]) || (a[2] <=> b[2]) }

In theory, it should return the result of the first comparison that doesn't match. This requires that || returns an operand rather than equating true/false from them.

Potentially, ?: might handle it if || can't:

list.sort{ a,b -> ((a[0] <=> b[0]) ?: (a[1] <=> b[1])) ?: (a[2] <=> b[2]) }
Jonathan Lonowski
That seems to work well.
Ying
+1  A: 

If you want to sort arrays of arbitrary (though homogenous) length, you can use this and it will do it in a single pass:

def list = [[2, 0, 1], [1, 5, 2], [1, 0, 3]]

list.sort { a, b -> 
    for (int i : (0..<a.size())) {
        def comparison = (a[i] <=> b[i])
        if (comparison) return comparison
    } 
    return 0
}

assert list == [[1, 0, 3], [1, 5, 2], [2, 0, 1]]
Ted Naleid
+1  A: 

you can use kobo-commons' CollectionUtils library.

http://wiki.github.com/kobo/kobo-commons/sort-by-multiple-keys

import org.jggug.kobo.commons.lang.CollectionUtils

CollectionUtils.extendMetaClass()


list = [[2, 0, 1], [1, 5, 2], [1, 0, 3]]
list = list.sort{ [ it[0], it[1], it[2] ]} // sort by multiple keys
assert list == [[1, 0, 3], [1, 5, 2], [2, 0, 1]]

list2 = [ [name:"a", age:13], [name:"a",age:15], [name:"b", age:13] ]
list2 = list2.sort{[it.name, it.age] } // sort by name and age
assert list2 == [[name:"a", age:13], [name:"a", age:15], [name:"b", age:13]]