Actually Extending It
In order to actually extend Array.prototype.sort
, we have a couple options:
- Mutate its signature
- Sort in multiplicity using Decorators | Adapters ( Parent Pattern: Wrapper )
I was in your same boat and decided to utilize the 2nd approach:
private sortAddresses = (a, b) => {
let iPrimeFlag = this.sortAddressesByPrimaryFlag(a, b);
let iAlphaNum = this.sortAddressesByAlphaNum(a, b);
if (iPrimeFlag === 1) return 1;
else return iAlphaNum;
};
private sortAddressesByPrimaryFlag(a, b) {
if (b.primaryFlag > a.primaryFlag) return 1;
if (b.primaryFlag < a.primaryFlag) return -1;
return 0;
}
private sortAddressesByAlphaNum(a, b) {
let aAddress = this.$.formatAddress(a);
let bAddress = this.$.formatAddress(b);
if (aAddress > bAddress) return 1;
if (aAddress < bAddress) return -1;
return 0;
}
Intent
I'm already calling this.addresses.sort(this.sortAddresses)
in several places and I'd like to keep my ChangeCost low -- especially, knowing that we may get requirements to sort on even more heuristics.
So, in order to follow The Gang of Four's Two 'Rules of Thumb' --
Program to an interface, not an implementation.
and
Encapsulate what varies.
-- I decided to keep my signature the same and wrap my original method.
It would be useful if we didn't have to go through and change each line where we invoke this.addresses.sort
. Instead, we'd like to be able to add an indefinite number of sorting "heuristics" to the action of sorting.
The goal is to prioritize address objects whose primaryFlag
is 'Y'
and then take the address string -- '0000 Some St, #0000, City, ST 00000'
-- and sort these alphanumerically. Since 'Y'
is >
'N'
, we'd like to move it up in the list, visually, by lowering its index. Sorting the address string alphanumerically says that if 'Colorado'
is >
'Alabama'
, then we should bump 'Colorado'
down in the list visually by increasing its index.
Usage
This is used for sorting Addresses by different values. One value, primaryFlag
, is to denote if its the [ only ] default address; in my case, primaryFlag
is a sting of 'Y'
or 'N'
, not a boolean (ask my Back-End teammates why in the world?). The other value, this.$.formatAddress(a|b)
, takes these address [object Object]
's -- a
and b
-- and invokes formatAddress
off of my Sandbox this.$
.
The line if (iPrimeFlag === 1) return 1;
is saying, "anytime primaryFlag is 1, just bump that toward the head (beginning) of the array, otherwise, do whatever the alphanumeric heuristic decides", which allows us to prioritize by one heuristic while falling back on another.
Also note, .bind(undefined, 'prop')
is not being used in my actual code as I don't need it; this is just here for demonstrative purposes.
Now, I know I'm that person who provided some TypeScript -- lemme know if you don't understand what's happening in this code :)
Cheers!