Jump to content
muppet77

small tweak to rank an array

Recommended Posts

with this third party code

function rank($input) 
{
  $output = array();
  $ranking = $input; sort($ranking); $ranking = array_flip($ranking);
  $last_val = -1;
  foreach($ranking as $key => $val){
    $repetitions = ($val-$last_val-1);
    $last_val = $val;
    if($repetitions) {    
      $ranking[$key] = (($val*($repetitions+1))-($repetitions+1)*(($repetitions)/2))/($repetitions+1)+1 ;
    } else {
      $ranking[$key] = $val+1;
    }
  }
  foreach($input as $key => $val){
    $output[$key] = $ranking[$val];
  }
  return $output;
}


$a = array(4,76,34,13,34);
$c = rank($a);
print_r($c);

that ranks an array, how could i tweak it to rank the other way round, so the highest value = 1, etc?

 

thanks

 

Share this post


Link to post
Share on other sites

Without thinking too hard about it,

sort($ranking);
that is the only place in the code that does any kind of sorting, so to reverse the results you would reverse the sorting.
  • Like 1

Share this post


Link to post
Share on other sites

try

function rank($input)
{
    $ranked = [];
    arsort($input);
    $prev = null;
    $rank = $count = 0;
    foreach ($input as $k => $v) {
        ++$count;
        $rank = $v==$prev ? $rank : $count ;
        $ranked[$k] = $rank;
        $prev = $v;
    }
    return $ranked;
}

$a = array('A'=>4, 'B'=>76, 'C'=>34, 'D'=>13, 'E'=>34);
$b = rank($a);
#------------------------------#
#   output results             #
#------------------------------#
echo '<pre>';
echo "<br>Input - with rank<br>";
foreach ($a as $k => $v) {
    printf('%s | %3d | %3d<br>', $k, $v, $b[$k]);
}
echo "<br>Order by rank<br>";
asort($b);
foreach ($b as $k => $r) {
    printf('%s | %3d | %3d <br>', $k, $a[$k], $r);
}

/* giving: ***********************************

    Input - with rank
        A |   4 |   5
        B |  76 |   1
        C |  34 |   2
        D |  13 |   4
        E |  34 |   2

    Order by rank
        B |  76 |   1 
        C |  34 |   2 
        E |  34 |   2 
        D |  13 |   4 
        A |   4 |   5
        
**********************************************/
  • Like 2

Share this post


Link to post
Share on other sites

Thanks both.

 

What’s the name of the new ranked array, Barand?

Share this post


Link to post
Share on other sites

I'll give you a clue.

 

There are two arrays ($a and $b) and $a contains the original input.

 

 

$a = Array
(
[A] => 4
[B] => 76
[C] => 34
[D] => 13
[E] => 34
)
$b = Array
(
[B] => 1
[C] => 2
[E] => 2
[D] => 4
[A] => 5
)
Edited by Barand
  • Like 1

Share this post


Link to post
Share on other sites

haha. thanks Barand.

 

I've now realised that my data are non - integer numbers and so ranking doesn't quite work anymore in this way.

 

i have an integer and i've added a random number that has about 5 decimal places - i then need to rank these non integers in the array.

 

Is there a quick and easy fix to rank non integers?

thanks

Edited by muppet77

Share this post


Link to post
Share on other sites

The rank() function works exactly the same with floats or integers. The only things that would change in my code are the format strings in the printf() functions so they display float values.

 

function rank($input)
{
    $ranked = [];
    arsort($input);
    $prev = null;
    $rank = $count = 0;
    foreach ($input as $k => $v) {
        ++$count;
        $rank = $v==$prev ? $rank : $count ;
        $ranked[$k] = $rank;
        $prev = $v;
    }
    return $ranked;
}

$a = array('A'=>4.12345, 'B'=>76.09871, 'C'=>34.12345, 'D'=>13.65421, 'E'=>34.12345);
$b = rank($a);
#------------------------------#
#   output results             #
#------------------------------#
echo '<pre>';
echo "<br>Input - with rank<br>";
foreach ($a as $k => $v) {
    printf('%s | %8.5f | %3d<br>', $k, $v, $b[$k]);
}
echo "<br>Order by rank<br>";
asort($b);
foreach ($b as $k => $r) {
    printf('%s | %8.5f | %3d <br>', $k, $a[$k], $r);
}

 

Results

 

Input - with rank
A | 4.12345 | 5
B | 76.09871 | 1
C | 34.12345 | 2
D | 13.65421 | 4
E | 34.12345 | 2

Order by rank
B | 76.09871 | 1
C | 34.12345 | 2
E | 34.12345 | 2
D | 13.65421 | 4
A | 4.12345 | 5
  • Like 1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.