15.9.11

Sorting an array on multiple fields of a nested object...

I recently ran into the need to sort an array of AS3 objects by multiple fields of a nested object. In JSON, the AS3 would look sort of like this:
[

    {"feature":
        {"attributes":{"country":"Brazil", "state":"Bahia"}
        {"geometry":.....}
    },
    {"feature":
        {"attributes":{"country":"Brazil", "state":"Sao Paulo"}
        {"geometry":.....}
    }
]
Ok, so the example above is already sorted, but imagine this sort of array and needing to sort alphabetically descending first by country and then by system. I'm pretty sure that the AS3 sortOn() only handles first-level properties for each object in the array. I chose to write a custom function which would use array.sort():
private function nestedTwoColumnSort(array:Array, parentField:String, 
                                     sortField1:String, sortField2:String):void
{
    function multipleSort(a:Object, b:Object):Object
    {
        var w:String = a[parentField][sortField1].toLowerCase();
        var x:String = b[parentField][sortField1].toLowerCase();
        
        //sort first field
        if(w < x)
        {
            return -1;
        }
        
        if(w > x)
        {
            return 1;
        }
        
        //if first field is the same, then sort on second field
        if(w == x)
        {
            var y:String = a[parentField][sortField2].toLowerCase();
            var z:String = b[parentField][sortField2].toLowerCase();
            
            if(y < z)
            {
                return -1;
            }
            
            if(y > z)
            {
                return 1;
            }
        }
        
        return 0;
    }
    
    //Sort once for the first field
    array.sort(multipleSort);
    
    //Sort once for second field
    array.sort(multipleSort);
}
The nestedTwoColumnSort function takes the array, the name of the nested object, and the two fields you wish to sort by. It then runs the sort once to fully sort the first field, then again banking on all first fields to be the same.

Here's the actual function where I call the sort function:
private function onFeaturesLoadComplete(event:AppEvent):void
{
    var features:Array = event.data as Array;
    this.nestedTwoColumnSort(features, 'attributes', 'country', 'system');

    blah blah blah....
There very well might be a better way to do this,  but this was pretty straightforward to implement and I'm not seeing any noticeable performance issues in the application (but it also only runs once in the app...). 

I would love to hear how others accomplish the same task.

No comments:

Post a Comment