Using ColdFusion to sort an multi-dimensional array based on a "Price per sq. ft" field from high to low.
It has been in production and worked in testing, but a case has come up that has yielded strange, unsorted results. I also ran this on the CFDOCS site using their ArraySort
code and got the same, incorrect sort results.
As you can see the results are not even really sorted.
Here's my code:
figures = [
{name='carl',price='117.5'},
{name='fen',price='116.4'},
{name='joe',price='86.3'}
];
arraySort(figures, function (a, b){
return compare(b.price, a.price);
});
writeDump(figures);
Results:
NAME joe
PRICE 86.3
NAME carl
PRICE 117.5
NAME fen
PRICE 116.4
It should be sorted in this order: 117.5, 116.4, 86.3.
I believe it's sorting in a way that makes 86.3
appear greater than the rest because it starts with an 8? I also tried without the quotes and got the wrong results as well.
I ran this same code on cfdocs.org and got the same, wrong results.
Am I doing something incorrectly in my sort parameters or on the callback?
Thank you!
The ArraySort callback function "compares two elements of the array" at a time, and should return one of the following values:
-1
if the first element is less than the second 0
if the first element is equal to the second 1
if first element is greater than the secondWhile the compare() function does return 1
,0
or -1
, it compares the elements as strings, which isn't going to produce the expected order for numeric values. As Shawn suggested, adding some debugging code will show the results of each comparison:
arraySort(figures, function (a, b){
local.num = compare(a.price, b.price);
local.text = local.num == -1 ? " less than " : (local.num == 0 ? " equals " : " greater than");
writeOutput("<br> "& a.price &" "& local.text &" "& b.price &" => "& local.num );
return local.num ;
});
.. demonstrating that a string comparison doesn't produce the same results as a numeric comparison:
To sort the "price" values as numbers, use arithmetic operators instead of compare(). For descending order (high to low):
arraySort(figures, function (a, b){
return (b.price < a.price) ? -1 : (b.price == a.price ? 0 : 1);
});
For ascending order (low to high), just swap the comparisons:
arraySort(figures, function (a, b){
return (a.price < b.price) ? -1 : (a.price == b.price ? 0 : 1);
});