Sorting List of Objects in Apex and JS

Sorting List of Objects in Apex and JS

As a Salesforce Developer, I've written numerous Apex Triggers, Apex Classes, and Lightning Web Components. Recently, I've found myself comparing Apex and JavaScript. I know they're quite different, with distinct use cases, but I've been thinking about how I can solve specific problems in each language. For example, How to manipulate collections, objects, and properties in both languages, as well as how to handle sorting. It's been an interesting exercise that helps me revise both languages in my head. Let's dive into discussing how to sort arrays in both Apex and JavaScript.

Let's begin with JavaScript, as it offers a straightforward way to sort arrays compared to Apex. Imagine we have an array of player objects, each containing properties like name and worldCup (representing their World Cup wins). Our goal is to sort this array based on the worldCup property of each player.

let players = [
    {name: 'Leo Messi', worldCup: 1},
    {name: 'Cristiano Ronaldo', worldCup: 0},
    {name: 'Ronaldo Nazario', worldCup: 2}
];

//ascending order (for number value)
//array.sort(comparatorFunction)
players.sort((player1, player2) => player1.worldCup - player2.worldCup );

/*debug
asc by wc [{"name":"Cristiano Ronaldo","worldCup":0},{"name":"Leo Messi","worldCup":1},{"name":"Ronaldo Nazario","worldCup":2}]
*/        

To sort an array in JavaScript, you can use the sort() method of the Array object (AKA Higher Order Function). This method takes a function as input. This input function compares pairs of elements in the array and tells sort() how to order them.

The input function needs to return a negative number if the first element should come before the second, a positive number if the first element should come after the second, and zero if they are equal. Based on these return values, sort() rearranges the array into the correct order.

Now, in Apex things are not as straightforward as JS. For Apex you have to use Comparator Interface. After the Salesforce new release, System.Comparator<sObject> Interface made the sorting of List with sObject easier than before. let's understand by example. First, we create the Apex class which implements System.Comparator<sObject>, which must implement the compare method and return an Integer. Source: Cool Stuff by Daniel Ballinger

public class sObjectComparator implements System.Comparator<sObject> {
    
    // Asc and Desc are reserved keywords in Apex!
    public enum SortOrder { Ascend, Descend}
    
    private Schema.sObjectField sortField;
    private DescribeFieldResult describeResult;
    
    public SortOrder order {
        get; 
        set {
            order = value;
        }
    }
    
    //constructor
    public sObjectComparator(Schema.sObjectField compareField) {
        sortField = compareField;
        //get the field info
        describeResult = sortField.getDescribe();  
        order = SortOrder.Ascend;
    }
       
    public integer compare(sObject s1, sObject s2) {
        
        integer compareResult;
        
        // Handle null objects before null field values
        if(s1 == null && s2 == null) {
            compareResult = 0;
        } else if (s1 == null) {
            compareResult = -1;
        } else if (s2 == null) {
            compareResult = 1;
        } else {
            object s1FieldValue = s1?.get(sortField);
            object s2FieldValue = s2?.get(sortField);
            
            // Handle null field values then actual value compares
            if(s1FieldValue == null && s2FieldValue == null) {
                compareResult = 0;
            } else if (s1FieldValue == null) {
                compareResult = -1;
            } else if (s2FieldValue == null) {
                compareResult = 1;
            } else {
                compareResult = compareFieldTypes(s1FieldValue, s2FieldValue);
            } 
        }

        if(order == SortOrder.Descend) {
            return compareResult * -1;
        }
        return compareResult;
    }

    private integer compareFieldTypes(object s1FieldValue, object s2FieldValue) {
        switch on (describeResult.getType()) {
            when String {
                string s1 = (string)s1FieldValue;
                string s2 = (string)s2FieldValue;
            	return (s1 < s2) ? -1 : (s1 > s2) ? 1 : 0;   
            } 
            when DateTime {
                DateTime s1 = (DateTime)s1FieldValue;
                DateTime s2 = (DateTime)s2FieldValue;
            	return (s1 < s2) ? -1 : (s1 > s2) ? 1 : 0;  
            }
            when Date {
                Date s1 = (Date)s1FieldValue;
                Date s2 = (Date)s2FieldValue;
            	return (s1 < s2) ? -1 : (s1 > s2) ? 1 : 0;  
            }
            when Integer {
                Integer s1 = (Integer)s1FieldValue;
                Integer s2 = (Integer)s2FieldValue;
            	return (s1 < s2) ? -1 : (s1 > s2) ? 1 : 0;  
            }
            when Double {
                Double s1 = (Double)s1FieldValue;
                Double s2 = (Double)s2FieldValue;
            	return (s1 < s2) ? -1 : (s1 > s2) ? 1 : 0;  
            }
            when Id {
                Id s1 = (Id)s1FieldValue;
                Id s2 = (Id)s2FieldValue;
            	return (s1 < s2) ? -1 : (s1 > s2) ? 1 : 0;  
            }
            when else {
                Assert.fail('Unable to compare field type: ' + describeResult.getType());
            }
        }
        return 0;
    }
}        

  • The above class implements the System.Comparator<sObject> interface, allowing it to be used for sorting lists of sObject records.
  • It defines an enum SortOrder with values Ascend and Descend to specify the sort order.
  • The class has a constructor that takes a Schema.sObjectField parameter, representing the field by which the sObject records will be sorted.
  • The compare method compares two sObject records based on the specified field. It handles cases where the records or field values are null.
  • The compareFieldTypes method is a helper method used to compare field values of different types (String, DateTime, Date, Integer, Double, Id).
  • The sorting order (ascending or descending) is determined by the order property, For Example purposes, we will go through only ascending (SortOrder.Ascend).By creating the above class most of your work is done. Not let's sort the list of sObject by their Field. Let's create an Apex method that sorts a list of Student__c records based on their Rank__c field.

public Static void sortStudents(){
        
        List<Student__c> studentList = new List<Student__c>();               
        studentList.add(new Student__c(Name='Ramos',Rank__c=6));        
        studentList.add(new Student__c(Name='Xavi',Rank__c=5));        
        studentList.add(new Student__c(Name='Busquets',Rank__c=3));        
        studentList.add(new Student__c(Name='Muller',Rank__c=4));        
        studentList.add(new Student__c(Name='Iniesta',Rank__c=1));        
        studentList.add(new Student__c(Name='Zidane',Rank__c=2));
        
        sObjectComparator comp = new sObjectComparator(Student__c.Rank__c);
        //pass the instance of sObjectComparator in sort method
        studentList.sort(comp);
        System.debug('Student__c list is '+studentList);
    }

/*
debug
Student__c list is (Student__c:{Name=Iniesta, Rank__c=1}, Student__c:{Name=Zidane, Rank__c=2}, Student__c:{Name=Busquets, Rank__c=3}, Student__c:{Name=Muller, Rank__c=4}, Student__c:{Name=Xavi, Rank__c=5}, Student__c:{Name=Ramos, Rank__c=6})
*/        

In the above example, after creating a bunch of Student__c records, create the instance of sObjectComparator (custom comparator class), specifying Student__c.Rank__c is the field to sort by. This instance is passed as a parameter to the sort method, which then sorts the list based on the specified field.

For example, I've only shown sorting in ascending order. However, you can modify the sObjectComparator class as you need, and can also make ASC/DESC as constructor parameters to control the order.

Thanks for your attention. I hope you have learned something new today.

What a way to teach something which is factual and inquisitive not only in terms of programming but in terms of football as well.

To view or add a comment, sign in

Others also viewed

Explore content categories