Avg. Rating 5.0
Tags:



Problem

How can I sort an array of objects with ColdFusion?

Solution

ColdFusion's struct data-type helps simplify sorting an array of objects (or other complex data-types). We will build a new struct where the key is the value we need to sort. We will also ensure that duplicate values are not lost in the process.

Detailed explanation

Setting up some Example Objects

Setting up the Example: Example Object
Notice the init function shows two different methods of populating the object from a struct that contains a matching key for our properties. This is simply a bonus for this entry. Both methods work well.

/** I am an example object for a Blog Post. */
component
        name            = 'Character'
{
        /** Who is our Video Game Character? */
        property name='Name';

        /** What video game does this character exist in? */
        property
                name='VideoGame';

        /** What is their score? This is just an example. */
        property
                name='Score';

        /** Construct */
        public function init (struct memento)
        {
                // Here is a way to explicitly set properties
                if (structKeyExists(arguments, 'memento')) {
                        setName(arguments.memento.name);
                        setVideoGame(arguments.memento.videoGame);
                        setScore(arguments.memento.score);
                }

                // This is a dynamic method. It does the same
                // exact work as above but the code wont need
                // to be maintained.
                if (structKeyExists(arguments, 'memento'))
                        for (local.k in arguments.memento)
                                evaluate("set#local.k#(arguments.memento[local.k])");

                return this;
        };
}

Setting up the Example: Example Data

examples = [
                // My Video Game Handle
                 {name = 'Aaron Greenlee (CrazedFan)',videoGame ='Call Of Duty 4', score = 19856 }
                
                // One of my favorite games
                ,{name = 'Gordon Freeman', videoGame ='Half-Life Series', score = 1980 }
                
                // COD/MW Rocks
                ,{name = 'John "Soap" MacTavish', videoGame ='Modern Warfare Series', score = 154 }
                
                // Love to Mario!
                ,{name = 'Mario', videoGame ='Super Mario Bors.', score = 192553 }
                
                // Back Back Forward
                ,{name = 'Raden', videoGame ='Mortal Kombat', score = 1545 }
                
                // Valve Software is an amazing company. Mass respect.
                ,{name = 'GLaDOS', videoGame ='PORTAL', score = 0 }
                
                // I never finish these games
                ,{name = 'Link', videoGame ='Zelda', score = '0' }
        ];

Setting up the Example: Populating Some Objects
The following code passes the struct with key that match the properties of our object. The object's init method will populate the object instance with the values from the struct.

// Populate some objects
        objects = [];
        n = arrayLen(examples);
        for(i=1; i<=n; i++)
                arrayAppend(objects, entityNew('Character').init(examples[i]) );

Sorting our Array of Objects

Step 1: Create and Sort a Struct
As we loop over the object I am concatenating the value to sort with a UUID to ensure each key is unique. Otherwise, objects with duplicate values are lost.

// Hold all our sorts
        sort = {
                 sortedStruct = { byName = {}, byScore = {} }
                ,sortedArrays = { byName = [], byScore = [] }
        };

        // Sort into structs.
        // We simply let CF do the hard work
        n = arrayLen(objects);
        for (i=1; i <= n; i++) {
                // Each key in the struct is in the format of
                // {VALUE}.{RAND NUMBER} This is important otherwise any objects
                // with the same value would be lost.
                rn = randRange(1,100);
                sort.sortedStruct.byScore[ objects[i].getScore() & '.' & rn ] = objects[i];
                sort.sortedStruct.byName[ objects[i].getName() & '.' & rn ] = objects[i];
        }
        // The hard work is already done by ColdFusion as structs are sorted by default!
        writeDump(var=sort.sortedStruct.byScore,label='Struct Sorted by Score');
        writeDump(var=sort.sortedStruct.byName,label='Struct Sorted by Name');

If you needed to sort your value in ascending order you can stop here. Your struct (in this case, sort.sortedStruct) has our objects sorted by Name and Score in ascending order.

How can I sort an array of objects with ColdFusion?

Step 2: Sort into an Array.
Let's sort our objects within arrays. First, we will sort by name in ascending order:

// Sort the objects into an array by name.
        names = structKeyArray(sort.sortedStruct.byName);
        arraySort(names, 'text', 'asc');
        n = arrayLen(names);
        for (i=1; i <= n; i++)
                arrayAppend(sort.sortedArrays.byName, sort.sortedStruct.byName[ names[i] ]);

        writeDump(var=sort.sortedArrays.byName,label='Array Sorted by Name');

Pretty cool! But, we can also sort our array in descending order. To illustrate this, let's sort our objects by score in descending order.

// Similar work for sorting by score
        scores = structKeyArray(sort.sortedStruct.byScore);
        arraySort(scores, 'numeric', 'desc');
        n = arrayLen(scores);
        for (i=1; i <= n; i++)
                arrayAppend(sort.sortedArrays.byScore, sort.sortedStruct.byScore[ scores[i] ]);

        writeDump(var=sort.sortedArrays.byScore,label='Array Sorted by Score');

We now have a sorted array of objects! Please notice that the score was sorted as numeric. 

How can I sort an array of objects with ColdFusion?


+
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License. Permissions beyond the scope of this license, pertaining to the examples of code included within this work are available at Adobe.

Report abuse

Related recipes