Skip to content Skip to sidebar Skip to footer

Javascript Sort Custom Comparator Function - Sorting A Sorted Array

I have an array of objects of the following form: arr[0] = { 'item1' : 1234, 'item2' : 'a string' }; I sort it first by 'item1' which is straightforward. Now i want to sort arr (w

Solution 1:

You can have four different comparison functions - one sorting by item1, one by item2, one by item1 then item2 and one by item2 then item1.

E.g.:

arr.sort(function(a,b){
  if(a.item1 == b.item1){
    return a.item2 > b.item2 ? 1 : a.item2 < b.item2 ? -1 : 0;
  }

  return a.item1 > b.item1 ? 1 : -1;
});

Solution 2:

I hit the same question lately. Came with a similar solution than langpavel, but I prefer to split the thing in two. First a chained comparator helper that will allows multiple sort rule, each applied in order as a tie-breaker in case of equality:

typeComparator<T> = (a: T, b: T) =>number; // -1 | 0 | 1/**
     * Allow to chain multiple comparators, each one called to break equality from the previous one.
     */function chainedComparator<T>(...comparators: Comparator<T>[]): Comparator<T> {
        return(a: T, b: T) => {
            let order = 0;
            let i = 0;
    
            while (!order && comparators[i]) {
                order = comparators[i++](a, b);
            }
    
            return order;
        };
    }

I like it, because it takes and return sort comparator. So if you have a collection of other comparators, they are easy to use.

Then you can simplify a bit your life with an additional helper. This one return a sort comparator based on the result of the passed lambda over each items.

typeComparable = string | number;

    /**
     * Returns a comparator which use an evaluationFunc on each item for comparison
     */function lambdaComparator<T>(evaluationFunc: ((item: T) =>Comparable), reversed = false): Comparator<T> {
        return(a: T, b: T) => {
            const valA = evaluationFunc(a);
            const valB = evaluationFunc(b);
            let order = 0;
    
            if (valA < valB) {
                order = -1;
            } elseif (valA > valB) {
                order = 1;
            }
            return reversed ? -order : order;
        };
    }

reversed here is not required to answer the question, but will allow to reverse the order easily.

To answer the question specifically, using our two comparators:

    arr.sort(chainedComparator(
        lambdaComparator(a => a.item1),
        lambdaComparator(a => a.item2.toLowerCase()) // "banana" before "Melon"
    ));

Because the original question was in pure JavaScript, precision: If you're not accustomed to TypeScript, you can get normal JavaScript just by removing the typing <T>, : T, : ((item: T) => Comparable) everywhere and the two type lines out.

Solution 3:

I'm using this helper in TypeScript:

// SourcetypeComparatorSelector<T> = (value: T, other: T) =>number | string | null;

exportfunction createComparator<T>(...selectors: ComparatorSelector<T>[]) {
  return(a: T, b: T) => {
    for (const selector of selectors) {
      const valA = selector(a, b);
      if (valA === null) continue;
      const valB = selector(b, a);
      if (valB === null || valA == valB) continue;
      if (valA > valB) return1;
      if (valA < valB) return -1;
    }
    return0;
  };
}

// Usage:constcandidates: any[] = [];
// ...
candidates.sort(createComparator(
  (x) => x.ambiguous,
  (_, y) => y.refCount, // DESC(x) => x.name.length,
  (x) => x.name,
));

Solution 4:

You can just import type-comparator with npm and then use queue to do the chaining:

const comparator = queue([
    map(x => x.item1, asc),
    map(x => x.item2, asc)
]);
arr.sort(comparator);

Solution 5:

Or as simple oneliner for first and second priority sort, you can expand it further as you wish, just replace the 0 with another comparison chain. Switch < and > or -1 and 1 for the reversed order.

someArray.sort(function(a,b) {
  return a.item1 > b.item1 ? 1 : a.item1 < b.item1 ? -1 : a.item2 > b.item2 ? 1 : a.item2 < b.item2 ? -1 : 0;
});

Post a Comment for "Javascript Sort Custom Comparator Function - Sorting A Sorted Array"