Just came across this topic while looking for a nice solution for myself. Just drop this here for the future. What I'm using is the following function:
/* Assign rank to each value of the array $in.
* Args:
* in (array): Array containing as set of numeric values.
*
* Returns:
* Returns an array of the same length with ranks. Highest
* values of $in get rank 1, lower values get higher ranks.
* The same values are attributed to the same ranks.
*/
function array_rank( $in ) {
# Keep input array "x" and replace values with rank.
# This preserves the order. Working on a copy called $x
# to set the ranks.
print "input\n";
print_r($in);
$x = $in; arsort($x);
print "sorted\n";
print_r($x);
# Initival values
$rank = 0;
$hiddenrank = 0;
$hold = null;
foreach ( $x as $key=>$val ) {
# Always increade hidden rank
$hiddenrank += 1;
# If current value is lower than previous:
# set new hold, and set rank to hiddenrank.
if ( is_null($hold) || $val < $hold ) {
$rank = $hiddenrank; $hold = $val;
}
# Set rank $rank for $in[$key]
$in[$key] = $rank;
}
print "ranking result\n";
print_r($in);
return $in;
}
$a = array(140,180,180,100);
array_rank( $a );
The print statements (development) return the following:
input
Array
(
[0] => 140
[1] => 180
[2] => 180
[3] => 100
)
sorted
Array
(
[2] => 180
[1] => 180
[0] => 140
[3] => 100
)
ranking result
Array
(
[0] => 3
[1] => 1
[2] => 1
[3] => 4
)
In case you want to have a reverse ranking (lower values are better) simply replace arsort
with asort
. In my case I am ranking points, the higher the better. The array (140,180,180,100)
gets the ranks (3,1,1,4)
. Players with the same amount of points get the same rank (in this case rank 1
) while rank 2
is left out.