Search code examples
javascriptsortingcustomizationes6-classcomparable

Comparable custom types which can be sorted as array items without defining an additional compare function inside sort()


Languages such as Python and Java have special methods for sorting custom classes. In JavaScript, toString() can be overridden, but this does not work easily for numeric values.

As a workaround, I added a method called compareTo() to the class, although this still requires a function to call it.

class NumericSortable {
    constructor(newVal) {
        this.val = newVal
    }
    compareTo(other) {
        return this.val - other.val
    }
}
const objectList = [
    new NumericSortable(3),
    new NumericSortable(1),
    new NumericSortable(20),
]
objectList.sort(
    function(a, b) { return a.compareTo(b) })
console.log(objectList)

Is there a way to modify the class so it can be sorted without requiring a function to be defined inside sort()?

Perhaps there is a good way to override toString() that will work for numeric values. However, solutions such as localeCompare() or a collator require two arguments, and they would not be passed to the overridden toString() method at the same time.


Solution

  • You can add a static method to your NumericSortable class, and pass that into the sort call. This idea can be extended to any custom class that need to define how two instances are to be compared for sorting.

    class NumericSortable  {
      constructor(value) {
        this.value = value;
      }
      
      static compare(a,b) {
        return a.value - b.value;
      }
    }
    
    const arr = [
      new NumericSortable(3),
      new NumericSortable(1),
      new NumericSortable(20),
    ];
    
    arr.sort(NumericSortable.compare);
    
    console.log(arr);
    

    This makes things more explicit, and easier for anyone else reading the code to reason about how the array is being sorted.