Reputation: 179
I have an array with these values, Array ( [0] => 12 [1] => 17 [2] => 5 [3] => 27 [4] => 5 )
and I need to find out ranking/position of each value
ie,
for 27 - Rank 1
for 17 - Rank 2
for 12 - Rank 3
for 5 - Rank 4
for 5 - Rank 4 (duplicate value in the array)
and these need to be in the same order as the array, so that output should be as follow
12 - Rank 3
17 - Rank 2
5 - Rank 4
27 - Rank 1
5 - Rank 4
Upvotes: 0
Views: 13436
Reputation: 99
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.
Upvotes: 2
Reputation: 4099
try this
$array = Array ( "0" => 12 , "1" => 17 , "2" => 5, "3" => 27, "4" => 5 );
$i=1;
foreach($array as $key=>$values)
{
$max = max($array);
echo "\n".$max." rank is ". $i."\n";
$keys = array_search($max, $array);
unset($array[$keys]);
if(sizeof($array) >0)
if(!in_array($max,$array))
$i++;
}
Upvotes: 2
Reputation: 387
This should work (including duplicate values having the same rank):
$values = array();
$values[0] = 5;
$values[1] = 12;
$values[2] = 19;
$values[3] = 9;
$values[4] = 5;
$ordered_values = $values;
rsort($ordered_values);
foreach ($values as $key => $value) {
foreach ($ordered_values as $ordered_key => $ordered_value) {
if ($value === $ordered_value) {
$key = $ordered_key;
break;
}
}
echo $value . '- Rank: ' . ((int) $key + 1) . '<br/>';
}
Upvotes: 5
Reputation: 2600
one problem you have is that you want some return value that has 2 times an identical value and key (5=>rank4). So you cannot do an array with ranks as key nor with values as key. In this example i simply made a 2 dimensional array.
<?php
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 1);
// your original input
$original = array(12, 17, 5, 27, 5);
// strip duplicates as they are ranked equally
$rankings = array_unique($original);
// apply some sorting so that the ranks are now given by the keys.
rsort($rankings);
// now just use the origincal array and lookup the rankings for each value
$return = array();
foreach($original as $value)
{
$rankedValue = array();
$rankedValue['value'] = $value;
$rankedValue['rank'] = array_search($value, $rankings) + 1;
$return[] = $rankedValue;
}
var_dump($return);
Upvotes: 0
Reputation: 476
You can probably sort the array by the values:
$ranked = sort($arrayValues);
after this, you can do a for loop, looping through the $ranked
array, then printing the arrays in order:
for($i = 0; $i < length($ranked); $i++){
for($j = 0; $j < length($arrayValues); $j++){
if($arrayValues[$i] == $sorted[$j]){
echo $arrayValues[$i] . ' has rank ' . $j;
}
}
}
Upvotes: -1