There’s now a small, solid group working on Astoria Digital’s MuckRock dataviz project. In fact, Chris DeLuca recently published a post about some developer onboarding issues with the dataviz library we are using for the project. We have prevailed, but it took some putting our heads together last weekend.
A simple version of the problem
Say you have a list of prices that you want to sort:
const prices = [3, 5, 370, 8]; const sortedPrices = prices.sort();
What do you think
sortedPrices will look like?
For Chrome and Node.js, you are correct if you guessed:
[ 3, 370, 5, 8 ]
Because (via MDN):
The default sort order is ascending, built upon converting the elements into strings, then comparing their sequences of UTF-16 code units values.
So the output above is the correct ascending order when the numbers are coerced to strings:
console.log("3" < "350"); // true console.log("350" < "5"); // true; gotcha!
The wild thing here is that Safari does what you would expect, leading to more confusion:
[ 3, 5, 8, 370 ]
Array.prototype.sort() with no argument is not going to work for reliably sorting numbers. To make sure the sort behaves as we expect everywhere, we’ll have to supply our own compare function.
This won’t work
We could try using a greater-than/less-than comparitive operator:
const sortedPrices = prices.sort((second, first) => first < second);
But recall that the parameters you receive in the callback (
first) are strings, not numbers, so here’s what you’ll get:
[ 3, 5, 370, 8 ]
“3” < “5” // true “5” < “370” // true “370” < “8” // true!
The comparison operators don’t coerce strings to numbers, so you just get a different flavor of the problem we saw when passing no argument to
But this will work
const prices = [3, 5, 370, 8]; const sortedPrices = prices.sort((second, first) => second - first);
second - first is a negative number,
second will be sorted down in the array, step-by-step, until it ends up in its correct spot in the ascending order.
Our new compare function gives us:
[ 3, 5, 8, 370 ]