Reputation: 7805
I have a multi-dimensional array. Inside each array, their is a sub value called "elo-rating". I want to sort my array based on this sub value.
So I take my array, called $newRanks
and run it through the following:
uasort($newRanks, create_function(
'$b, $a', 'return $a["elo_rating"] - $b["elo_rating"];'
));
After running through that code, my array returns as follows:
array:52 [
"3-1154" => array:4 [
"league_id" => 3
"user_id" => 1154
"elo_matches" => 8
"elo_rating" => 1224.47797881
]
"3-205" => array:4 [
"league_id" => 3
"user_id" => 205
"elo_matches" => 11
"elo_rating" => 1207.86593741
]
"3-1" => array:4 [
"league_id" => 3
"user_id" => 1
"elo_matches" => 17
"elo_rating" => 1206.60264689
]
"3-285" => array:4 [
"league_id" => 3
"user_id" => 285
"elo_matches" => 4
"elo_rating" => 1187.31524255
]
"3-259" => array:4 [
"league_id" => 3
"user_id" => 259
"elo_matches" => 4
"elo_rating" => 1173.02391767
]
"3-12689" => array:4 [
"league_id" => 3
"user_id" => 12689
"elo_matches" => 4
"elo_rating" => 1167.46830619
]
"3-1603" => array:4 [
"league_id" => 3
"user_id" => 1603
"elo_matches" => 13
"elo_rating" => 1153.3060092
]
"3-16" => array:4 [
"league_id" => 3
"user_id" => 16
"elo_matches" => 7
"elo_rating" => 1146.65083202
]
"3-1609" => array:4 [
"league_id" => 3
"user_id" => 1609
"elo_matches" => 3
"elo_rating" => 1122.679103
]
"3-333" => array:4 [
"league_id" => 3
"user_id" => 333
"elo_matches" => 5
"elo_rating" => 1112.56694511
]
"3-10030" => array:4 [
"league_id" => 3
"user_id" => 10030
"elo_matches" => 4
"elo_rating" => 1091.27782914
]
"3-378" => array:4 [
"league_id" => 3
"user_id" => 378
"elo_matches" => 9
"elo_rating" => 1082.0354022
]
"3-6107" => array:4 [
"league_id" => 3
"user_id" => 6107
"elo_matches" => 5
"elo_rating" => 1059.74850166
]
"3-5179" => array:4 [
"league_id" => 3
"user_id" => 5179
"elo_matches" => 3
"elo_rating" => 1046.60181418
]
"3-1476" => array:4 [
"league_id" => 3
"user_id" => 1476
"elo_matches" => 9
"elo_rating" => 1038.88789903
]
"3-70" => array:4 [
"league_id" => 3
"user_id" => 70
"elo_matches" => 8
"elo_rating" => 1038.63959146
]
"3-303" => array:4 [
"league_id" => 3
"user_id" => 303
"elo_matches" => 7
"elo_rating" => 1039.26666217
]
"3-59" => array:4 [
"league_id" => 3
"user_id" => 59
"elo_matches" => 1
"elo_rating" => 1033.78309445
]
"3-1017" => array:4 [
"league_id" => 3
"user_id" => 1017
"elo_matches" => 4
"elo_rating" => 1002.79264647
]
"3-632" => array:4 [
"league_id" => 3
"user_id" => 632
"elo_matches" => 3
"elo_rating" => 1002.2039368
]
"3-177" => array:4 [
"league_id" => 3
"user_id" => 177
"elo_matches" => 4
"elo_rating" => 994.838857477
]
"3-12466" => array:4 [
"league_id" => 3
"user_id" => 12466
"elo_matches" => 4
"elo_rating" => 994.761652125
]
"3-9725" => array:4 [
"league_id" => 3
"user_id" => 9725
"elo_matches" => 7
"elo_rating" => 994.520367143
]
"3-1593" => array:4 [
"league_id" => 3
"user_id" => 1593
"elo_matches" => 4
"elo_rating" => 987.448354356
]
"3-78" => array:4 [
"league_id" => 3
"user_id" => 78
"elo_matches" => 16
"elo_rating" => 984.927509938
]
"3-20837" => array:4 [
"league_id" => 3
"user_id" => 20837
"elo_matches" => 4
"elo_rating" => 981.533602402
]
"3-25" => array:4 [
"league_id" => 3
"user_id" => 25
"elo_matches" => 3
"elo_rating" => 977.651701927
]
"3-2056" => array:4 [
"league_id" => 3
"user_id" => 2056
"elo_matches" => 8
"elo_rating" => 978.374247502
]
"3-14300" => array:4 [
"league_id" => 3
"user_id" => 14300
"elo_matches" => 9
"elo_rating" => 958.218292232
]
"3-16900" => array:4 [
"league_id" => 3
"user_id" => 16900
"elo_matches" => 3
"elo_rating" => 957.66758785
]
"3-5" => array:4 [
"league_id" => 3
"user_id" => 5
"elo_matches" => 3
"elo_rating" => 955.441682773
]
"3-11793" => array:4 [
"league_id" => 3
"user_id" => 11793
"elo_matches" => 3
"elo_rating" => 956.118019821
]
"3-23" => array:4 [
"league_id" => 3
"user_id" => 23
"elo_matches" => 1
"elo_rating" => 950.0
]
"3-160" => array:4 [
"league_id" => 3
"user_id" => 160
"elo_matches" => 6
"elo_rating" => 946.346810828
]
"3-11882" => array:4 [
"league_id" => 3
"user_id" => 11882
"elo_matches" => 3
"elo_rating" => 943.113557791
]
"3-178" => array:4 [
"league_id" => 3
"user_id" => 178
"elo_matches" => 3
"elo_rating" => 940.38037017
]
"3-2113" => array:4 [
"league_id" => 3
"user_id" => 2113
"elo_matches" => 3
"elo_rating" => 940.343382565
]
"3-1334" => array:4 [
"league_id" => 3
"user_id" => 1334
"elo_matches" => 2
"elo_rating" => 923.336202927
]
"3-184" => array:4 [
"league_id" => 3
"user_id" => 184
"elo_matches" => 2
"elo_rating" => 920.326252901
]
"3-2162" => array:4 [
"league_id" => 3
"user_id" => 2162
"elo_matches" => 2
"elo_rating" => 917.932985501
]
"3-2058" => array:4 [
"league_id" => 3
"user_id" => 2058
"elo_matches" => 6
"elo_rating" => 905.641833006
]
"3-1951" => array:4 [
"league_id" => 3
"user_id" => 1951
"elo_matches" => 2
"elo_rating" => 906.136056131
]
"3-1749" => array:4 [
"league_id" => 3
"user_id" => 1749
"elo_matches" => 2
"elo_rating" => 905.570092295
]
"3-15296" => array:4 [
"league_id" => 3
"user_id" => 15296
"elo_matches" => 2
"elo_rating" => 901.02829192
]
"3-11684" => array:4 [
"league_id" => 3
"user_id" => 11684
"elo_matches" => 2
"elo_rating" => 901.02829192
]
"3-940" => array:4 [
"league_id" => 3
"user_id" => 940
"elo_matches" => 2
"elo_rating" => 899.735074733
]
"3-12235" => array:4 [
"league_id" => 3
"user_id" => 12235
"elo_matches" => 2
"elo_rating" => 900.0
]
"3-2957" => array:4 [
"league_id" => 3
"user_id" => 2957
"elo_matches" => 2
"elo_rating" => 900.0
]
"3-14959" => array:4 [
"league_id" => 3
"user_id" => 14959
"elo_matches" => 2
"elo_rating" => 894.798068073
]
"3-779" => array:4 [
"league_id" => 3
"user_id" => 779
"elo_matches" => 5
"elo_rating" => 874.675970857
]
"3-110" => array:4 [
"league_id" => 3
"user_id" => 110
"elo_matches" => 4
"elo_rating" => 849.309123925
]
"3-5837" => array:4 [
"league_id" => 3
"user_id" => 5837
"elo_matches" => 4
"elo_rating" => 821.601462523
]
]
If you look closely at this resulting array, you'll notice that its not exactly sorted properly. For instance, it puts 1039.26666217
below both 1038.63959146
and 1038.88789903
.
Any ideas on how to fix this?
Upvotes: 0
Views: 48
Reputation: 32272
Two problems:
create_function()
which uses eval()
internally, which is a gaping security hole, and unnecessary to boot. Just use an actual anonymous function.So:
$epsilon = 0.000000001;
uasort(
$newRanks,
function($a,$b)use($epsilon}{
$diff = $a["elo_rating"] - $b["elo_rating"];
if( abs($diff) < $epsilon ) { return 0; }
else if( $diff > 0 ) { return 1; }
else { return -1; }
)
);
Where $epsilon
is a value chosen specifically for this comparison where you consider any $diff
smaller than that to be an equivalence, aka float/rounding error.
See: What is the most effective way for float and double comparison?
Upvotes: 1
Reputation: 5187
You are returning decimal values from your function, which the documentation warns against.
The comparison function must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second. Note that before PHP 7.0.0 this integer had to be in the range from -2147483648 to 2147483647.
Caution Returning non-integer values from the comparison function, such as float, will result in an internal cast to integer of the callback's return value. So values such as 0.99 and 0.1 will both be cast to an integer value of 0, which will compare such values as equal.
Change your function to return an integer to fix the issue.
uasort($newRanks, create_function(
'$b, $a', 'return ($a["elo_rating"] > $b["elo_rating"])?-1:1;'
));
Upvotes: 3