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.