Kristen Joseph-Delaffon
Kristen Joseph-Delaffon

Reputation: 1291

Ranking function with tie in multidimensional array

I have to make a ranking function.

In my $passages array, I have 'user', 'username', 'note' and 'classement' keys.

I want to set 'classement' key to rank by 'note' key and order array by 'username' key.

Here's what I tried :

for ($i = 0; $i < sizeof($passages); $i++) {
        for ($j = 0; $j < sizeof($passages); $j++) {
            $test = $this->compare($passages[$i]['note'], $passages[$j]['note']);
            if ($test < 0) {
                $tmp = $passages[$j];
                $passages[$j] = $passages[$i];
                $passages[$i] = $tmp;
            } else if ($test >= 0) {
                $tmp = $passages[$i];
                $passages[$i] = $passages[$j];
                $passages[$j] = $tmp;
            }
        }
    }

compare function :

if ($a==$b) return 0;
    return ($a<$b)?-1:1;

In this ranking function, I added a function to take care of ties :

$rank = 1;
    for ($i = 0; $i < $nbTotal; $i++) {
            // Si la note du passage actuel est égale à la note du passage précédent,
            // le classement est égal au classement du passage précédent
            if ($i > 0 && $passages[$i]['note'] == $passages[$i - 1]['note']) {
                $passages[$i]['classement'] = $passages[$i - 1]['classement'];
            }
            // Sinon le classement est égal à la valeur de $rank
            else {
                $passages[$i]['classement'] = $rank;
            }
            $rank++;
    }

I tested my function and it's returning an array ordered by user Id and with 'classement' key = user Id order.

What I get :

$passages = array(
                   array(['id'] => "1"
                         ['username'] => "1124", 
                         ['note'] => "22",
                         ['classement'] => "1"),
                   array(['id'] => "2",
                         ['username'] => "1001", 
                         ['note'] => "10",
                         ['classement'] => "2"),
                   array(['id'] => "3",
                         ['username'] => "1100", 
                         ['note'] => "15",
                         ['classement'] => "3"),
                   array(['id'] => "4",
                         ['username'] => "1120", 
                         ['note'] => "5",
                         ['classement'] => "4"),
                   array(['id'] => "5",
                         ['username'] => "1200", 
                         ['note'] => "15",
                         ['classement'] => "5")
           );

What I want :

$passages = array(
                   array(['id'] => "2"
                         ['username'] => "1001", 
                         ['note'] => "10",
                         ['classement'] => "4"),
                   array(['id'] => "3",
                         ['username'] => "1100", 
                         ['note'] => "15",
                         ['classement'] => "2"),
                   array(['id'] => "4",
                         ['username'] => "1120", 
                         ['note'] => "5",
                         ['classement'] => "5")
                   array(['id'] => "1",
                         ['username'] => "1124", 
                         ['note'] => "22",
                         ['classement'] => "1"),
                   array(['id'] => "5",
                         ['username'] => "1200", 
                         ['note'] => "15",
                         ['classement'] => "2")
           );

Upvotes: 0

Views: 87

Answers (1)

Viktor
Viktor

Reputation: 3536

Step 1: Sort $passages array by note key descendingly

array_multisort(array_column($passages, 'note'), SORT_DESC, SORT_NUMERIC, $passages);

Step 2: Set rank

$rank = 1;
$nbTotal = count($passages);

for ($i = 0; $i < $nbTotal; $i++) {
    // Si la note du passage actuel est égale à la note du passage précédent,
    // le classement est égal au classement du passage précédent
    if ($i > 0 && $passages[$i]['note'] == $passages[$i - 1]['note']) {
        $passages[$i]['classement'] = $passages[$i - 1]['classement'];
    }
    // Sinon le classement est égal à la valeur de $rank
    else {
        $passages[$i]['classement'] = $rank;
    }
    $rank++;
}

Step 3: Sort $passages array by username key ascendingly

array_multisort(array_column($passages, 'username'), SORT_ASC, SORT_NUMERIC, $passages);

Upvotes: 1

Related Questions