Easily consumable slice multisorting

In various online discussions about the merits of Go, the pain of having to implement sort.Interface comes up, especially when one needs to sort a slice in multiple orders. Personally, implementing sort.Interface is no more than a buzz in my ear, but detractors tend to highlight it strongly anyway.

During one of these discussions I wrote up a pattern that allows you to sort using an anonymous less func. Of course, this comes with the downside of another indirection, and yet more type implementation, so I could only recommend this pattern if the performance impact is small and you need to sort in many (>3) orders and/or want to be able to quickly define new sorting orders.

The consuming syntax is actually pretty agreeable, and it comes with a feature to easily combine multiple orderings in a hierarchy. This isn’t extremely novel and I wouldn’t be surprised if I had actually seen this pattern elsewhere and since forgotten about it, but I thought I’d share anyway. Example usage:

var orderx datalessfn = func(a, b data) bool { return a.x < b.x }
sort.Sort(slice.By(orderx))  // sorts slice by data.x
ordery := func(a, b data) bool { return a.y < b.y }
sort.Sort(slice.By(orderx.Then(ordery))) // sorts slice by data.x, or when x is equal, then data.y


Similar idea but older implementation:

Oh yeah, I had forgotten about that.

So slice uses reflect and unsafe to sort arbitrary slices with just a less fn (and no additional types or methods). My pattern above requires a couple types and several small functions, but once they’re made allows you to sort that type by any anonymous less fn (using no unsafe or reflect).

Another difference is that the less func in slice must be closed around the original slice, whereas mine gives you copies of the elements at i,j so the func can be reused for different slices.

I’m not sure which would sort faster, but I have a feeling that mine would. Of course, slice wins the implementation speed race (there is none). :slight_smile:


This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.