Search code examples
phparraysrankingrank

Perfect Ranking with ties using PHP alone


In my attempt to find the perfect ranking solution with ties, I was stuck at giving the correct ranking. Codes will explain what I am trying to achieve better:

I have the following array:

$standings = array(
    'player_1' => 30,
    'player_2' => 26,
    'player_3' => 28,
    'player_9' => 28
);

Now in order to rank it with ties, I have the following function:

function setRanking($standings) {
    $rankings = array();
    arsort($standings);
    $rank = 1;
    $tie_rank = 0;
    $prev_score = -1;
    foreach ($standings as $name => $score) {
        if ($score != $prev_score) {  //this score is not a tie
            $count = 0;
            $prev_score = $score; 
            $rankings[$name] = array('score' => $score, 'rank' => $rank);
        } else { //this score is a tie
            $prev_score = $score;
            if ($count++ == 0) {
                $tie_rank = $rank - 1;
            }
            $rankings[$name] = array('score' => $score, 'rank' => $tie_rank);
        }
        $rank++;
    }
    return $rankings;
}
echo '<pre>';
print_r(setRanking($standings));

Output:

Array
(
    [player_1] => Array
        (
            [score] => 30
            [rank] => 1
        )

    [player_3] => Array
        (
            [score] => 28
            [rank] => 2
        )

    [player_9] => Array
        (
            [score] => 28
            [rank] => 2
        )

    [player_2] => Array
        (
            [score] => 26
            [rank] => 4
        )

)

Expected Output:

Array
(
    [player_1] => Array
        (
            [score] => 30
            [rank] => 1
        )

    [player_3] => Array
        (
            [score] => 28
            [rank] => 2
        )

    [player_9] => Array
        (
            [score] => 28
            [rank] => 2
        )

    [player_2] => Array
        (
            [score] => 26
            [rank] => 3
        )

)

The problem is it prints the ranking as 1,2,2,4 whereas it should print 1,2,2,3 according to my assumption. So how can it print 1,2,2,3? Where could thing possibly go wrong? Any help is appreciated. Thanks.


Solution

  • Just change your else block, You are not decrements your $rank value so its hold the same value as it is. You just do the $rank - 1 cause its just less 1 to store in a variable not change the main value.

    foreach ($standings as $name => $score) {
        if ($score != $prev_score) {  //this score is not a tie
            $count = 0;
            $prev_score = $score; 
            $rankings[$name] = array('score' => $score, 'rank' => $rank);
        } else { //this score is a tie
            $prev_score = $score;
            $rank--; // Decrements here
            if ($count++ == 0) {
                $tie_rank = $rank;
            }
            $rankings[$name] = array('score' => $score, 'rank' => $tie_rank);
        }
        $rank++;
    }
    return $rankings;