Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using `apply` to change a sort function

I have a sort function, let's call it mySort(a, b) that returns 1,0,-1 if a is smaller. equal, bigger than b. That way, I can do a myArray.sort(mySort) to sort my array.

I now have a view where the array needs to be sorted in a descending order. My first solution was to just do myArray.sort(mySort).reverse() (yes, I know it's not efficient, but the array contains less than 50 items). But I started thinking that maybe I can just add another parameter to my sort function, that will return the opposite result if set to false: mySort(a, b, ascending = true).

The problem is: if I want to use Array.sort I need to provide a function. Is there a way to use apply (or call?) to create a function that will have ascending set to false, in a way that would allow something like myArray.sort(myFunction.apply(null, [,,false]))? Because I don't see a way to provide a and b on the fly.

like image 739
Traveling Tech Guy Avatar asked Jul 23 '26 00:07

Traveling Tech Guy


2 Answers

You can use mySort.bind() to bind a context and initial arguments, but I don't think there's anything like that that will force later arguments while leaving the first 2 arguments alone.

You can use a wrapper function that adds an argument:

myArray.sort((a, b) => mySort(a, b, true));

or reverses the sign of the result:

myArray.sort((a, b) => -mySort(a, b));

or swaps the argument order:

myArray.sort((a, b) => mySort(b, a));

You can also create a higher order function that implements this.

function reverseArgs(func) {
    return function() {
        return func.apply(this, Array.from(arguments).reverse());
    };
}

myArray.sort(reverseArgs(mySort));
like image 93
Barmar Avatar answered Jul 25 '26 19:07

Barmar


This is an alternate solution, but I'd just wrap your sort function in another function.

function myRevSort(a, b) {
   return mySort(a, b) * -1;
}

Or, if you want a boolean flag (although that generally isn't recommended), you can just use it to pick the multiplier, then return a "sorter" function:

function newSorter(ascending = true) {
   var mult = ascending ? 1 : -1;

   return function(a, b) {
       return mySort(a, b) * mult;
   } 
}

Then use it like:

myArray.sort(newSorter(false));

A note though, I think "comparator" is a more appropriate name for these functions. sort sounds like the function that actually sorts the collection.

like image 21
Carcigenicate Avatar answered Jul 25 '26 19:07

Carcigenicate



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!