Richard over on CF-Talk asked about sorting arrays using a deep attribute. As far as I know, there is nothing built into ColdFusion that does this kind of thing automatically. I know that ColdFusion's StructSort() method allows the user to provide a path to the sub element on which the sorting is based, but there doesn't seem to be anything like this for Arrays.
This got me thinking; I am pretty sure I remember something about a "Sortable" interface that exists in other languages. This sounded like something that would be helpful for this situation. After a bit of experimentation, here is what I came up with. You need to have an abstract class "AbstractSortable". This defines the following comparative methods:
AbstractSortable::LT()
AbstractSortable::LTE()
AbstractSortable::EQ()
AbstractSortable::GTE()
AbstractSortable::GT()
It also has some other methods:
AbstractSortable::Init()
AbstractSortable::SetTarget()
AbstractSortable::SortArray()
The comparative methods are used during the sorting algorithm defined in the SortArray() method (which in our case is going to be a bubble sort).
One you have all that set up, you need a concrete class the overrides at least one of the comparative methods. Each comparative method that is overridden must take an object reference to which we will be comparing the concrete class's target object. Each method must return a boolean. For every "True" returned, the two items in comparison will be swapped.
Now that I have given a brief explanation, let's take a look at some code. Here is the abstract sortable class:
Launch code in new window » Download code as text file »
And, here is the sortable girl class which is a concrete instantiation of the AbstractSortable.cfc:
Launch code in new window » Download code as text file »
Notice that the SortableGirl.cfc component extends the AbstractSortable.cfc component. This means that the SortableGirl.cfc has all the methods of the AbstractSortable.cfc but overrides only the ones it defines. In our case, we are overriding the GT() method. This means that we intend to sort something in an ASCending manner. But, look at how we compare the two items; we are comparing the "Birthday" properties of the given objects. This is where you do the custom sorting. I use Birthday, but this could just have easily been something crazy like:
Launch code in new window » Download code as text file »
The point is, you can do any sort of comparison on the two objects you want so long as you return TRUE or FALSE.
Ok, now let's take a look at the sorting in action. I have set up an array of girls and given them random Birthdays:
Launch code in new window » Download code as text file »
Dumping out the arrGirls array we get:
| | | | ||
| | | | ||
| | | |
Notice that the girls are arranged in their original list sort, having nothing to do with their birthdays. Now, let's create an instance of the SortableGirl.cfc ColdFusion Component and use it to sort the array:
Launch code in new window » Download code as text file »
Once we instantiation the SortableGirl.cfc (which extends AbstractSortable.cfc) we call the method SortArray(). We pass in the array that we want to sort and the method we want to use for sorting (GT()). This will perform the Bubble Sort defined in the AbstractSortable.cfc and will give us the following:
| | | | ||
| | | | ||
| | | |
Now, all the girls are sorted in an ASCending order based on their birthdays. To sort in a DESCending order, all you would have to do is override the LT() method and run the sort again. The only down side to this is that you have to create a class that defines the way you want to sort. But, if your sort is going to be highly customized, this minor overhead is going to be worth the usability of it.
Download Code Snippet ZIP File
Comments (2) | Post Comment | Ask Ben | Permalink | Other Searches | Print Page
People! Please Stop Using Single Quotes!
Skin Spider : Tracking Video Usage Statics And Mass Deletion
Ben, just wanted to let you know, a year later, I found this very useful. Thanks!
Posted by Rob Pilic on Dec 7, 2007 at 5:17 PM
@Rob,
As always, I'm glad that I could help. Feel free to drop a line anytime you get stuck on something.
Posted by Ben Nadel on Dec 10, 2007 at 8:01 AM