-1

My array structure is as follows -

[
    [
        "points" => 10,
        "details" => ["name" => "Team A", "rank" => ""]
    ],
    [
        "points" => 10,
        "details" => ["name" => "Team B", "rank" => ""]
    ],
    [
        "points" => 8,
        "details" => ["name" => "Team C", "rank" => ""]
    ],
    [
        "points" => 6,
        "details" => ["name" => "Team D", "rank" => ""]
    ],
]

Now I want populate the array's "rank" value with the appropriate dense rank. Expected result:

[
    [
        "points" => 10,
        "details" => ["name" => "Team A", "rank" => 1]
    ],
    [
        "points" => 10,
        "details" => ["name" => "Team B", "rank" => 1]
    ],
    [
        "points" => 8,
        "details" => ["name" => "Team C", "rank" => 2]
    ],
    [
        "points" => 6,
        "details" => ["name" => "Team D", "rank" => 3]
    ],
]

How can I achieve this output? I tried looping through each element in the array and comparing points, but I didn't find that to be really efficient.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
skos
  • 4,102
  • 8
  • 36
  • 59

3 Answers3

1

How about to create another array and store desired result there

$array = array(
    array(
        "points" => 10,
        "details" => array(
            "name" => "Team A",
            "rank" => ""
        )
    ),
    array(
        "points" => 11,
        "details" => array(
            "name" => "Team B",
            "rank" => ""
        )
    )
);

$c = 0; // count identifier
$n = array(); // create new array

for ($i=0;$i<count($array);$i++){ // loop through each array
    foreach ($array[$i] as $value){ // loop through into sub arrays
        if (is_array($value)){
            $n[$i]['details'] = array(
                "name" => $value['name'],
                "rank" => $c
            );
            $c++;
        } else {
            $n[$i]['points'] = $value;
        }
    }
}

print_r($n);

Output will be:

Array ( [0] => Array ( [points] => 10 [details] => Array ( [name] => Team A [rank] => 0 ) ) [1] => Array ( [points] => 11 [details] => Array ( [name] => Team B [rank] => 1 ) ) ) 
nanobash
  • 5,419
  • 7
  • 38
  • 56
1

A bit bruteforce but it should work.

$array = array(
    array(
    "points" => 10,
    "details" => array(
        "name" => "Team A",
        "rank" => ""
    )
    ),
    array(
    "points" => 11,
    "details" => array(
        "name" => "Team B",
        "rank" => ""
    )
    ),
    array(
    "points" => 10,
    "details" => array(
        "name" => "Team A",
        "rank" => ""
    )
    ),
    array(
    "points" => 11,
    "details" => array(
        "name" => "Team B",
        "rank" => ""
    )
    )
);
$points = array();
foreach($array as $key => $arr){
    $points[] = $arr['points'];
}
asort($points);

foreach($points as $pkey => $point){
    foreach($array as $akey => $arr){
        if($point == $arr['points']){
            $array[$akey]['details']['rank'] = $pkey+1;
        }
    }
}


var_dump($array);
0

Since your multidimensional input array is already sorted descending by the points column, you can loop through the array and modify its rank data by reference while conditionally incrementing the rank variable.

Code: (Demo)

$denseRank = 0;
foreach ($array as ['points'=> $points, 'details' => ['rank' => &$rank]]) {
    $denseRanks[$points] ??= ++$denseRank;
    $rank = $denseRanks[$points];
}
var_export($array);

The above snippet uses "array destructuring" in the foreach() to declare only used variables; it is just as viable to declare &$row and then access its elements in the loop's body.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136