MaryCoding
MaryCoding

Reputation: 664

How to generate an array using 3rd-level values of a multi-dimensional array

As shown below I have a multi-dimensional array with an associative array in the third level that I am trying to manipulate based on gamesCount. I want to generate a new array of items with the highest gamesCount in each sport. Is there an efficient way to this without going overkill?

EDIT: It could be n number of sports hence the goal is to find the max number for gameCounts for each sport.

Initial array:

$array = [
    [
        ["sport" => "soccer", "gamesCount" => 5, "gamesId" => 1],
        ["sport" => "soccer", "gamesCount" => 3, "gamesId" => 2],
        ["sport" => "soccer", "gamesCount" => 10, "gamesId" => 3],
        ["sport" => "soccer", "gamesCount" => 10, "gamesId" => 4],
    ],
    [
        ["sport" => "basketball", "gamesCount" => 1, "gamesId" => 5],
        ["sport" => "basketball", "gamesCount" => 3, "gamesId" => 6],
        ["sport" => "basketball", "gamesCount" => 3, "gamesId" => 7],
        ["sport" => "basketball", "gamesCount" => 8, "gamesId" => 8],
    ]
];

Desired Result:

array(3) {
      [0]=>
      array(3) {
        ["sport"]=>
        string(6) "soccer"
        ["gamesCount"]=>
        int(10)
        ["gamesId"]=>
        int(3)
      }
      [1]=>
      array(3) {
        ["sport"]=>
        string(6) "soccer"
        ["gamesCount"]=>
        int(10)
        ["gamesId"]=>
        int(4)
      }
      [2]=>
      array(3) {
        ["sport"]=>
        string(10) "basketball"
        ["gamesCount"]=>
        int(5)
        ["gamesId"]=>
        int(8)
      }
}

Upvotes: 1

Views: 509

Answers (2)

mickmackusa
mickmackusa

Reputation: 47900

Input:

$array=[
    [
        ["sport"=>"soccer","gamesCount"=>5,"gamesId"=>1],
        ["sport"=>"soccer","gamesCount"=>3,"gamesId"=>2],
        ["sport"=>"soccer","gamesCount"=>10,"gamesId"=>3],
        ["sport"=>"soccer","gamesCount"=>10,"gamesId"=>4]
    ],
    [
        ["sport"=>"basketball","gamesCount"=>1,"gamesId"=>5],
        ["sport"=>"basketball","gamesCount"=>3,"gamesId"=>6],
        ["sport"=>"basketball","gamesCount"=>3,"gamesId"=>7],
        ["sport"=>"basketball","gamesCount"=>8,"gamesId"=>8]
    ]
];

Method #1 "The easiest to read version with two loops" (Demo)

foreach($array as $sport_array){
    $most_in_sport=max(array_column($sport_array,'gamesCount'));  // get highest gamesCount in sport's subarray      
    foreach($sport_array as $sport_row){
        if($sport_row['gamesCount']==$most_in_sport){  // only keep a sport's subarray (row) if its gamesCount is the highest in the sport
            $most_per_sport[]=$sport_row;
        }
    }
}
var_export($most_per_sport);

Method #2: "The obscenely convoluted variadic one-liner" php minimum version: 5.6 (For those who wish who do not fear the one-liner apocalypse -- reference: 1st comment @ https://stackoverflow.com/a/43950486/2943403.) (Demo)

var_export(array_merge(...array_map(function($sport_array){$most_in_sport=max(array_column($sport_array,'gamesCount')); return array_filter($sport_array,function($sport_row)use($most_in_sport){return $sport_row['gamesCount']==$most_in_sport;});},$array)));

Output:

array (
  0 => 
  array (
    'sport' => 'soccer',
    'gamesCount' => 10,
    'gamesId' => 3,
  ),
  1 => 
  array (
    'sport' => 'soccer',
    'gamesCount' => 10,
    'gamesId' => 4,
  ),
  2 => 
  array (
    'sport' => 'basketball',
    'gamesCount' => 8,
    'gamesId' => 8,
  ),
)

Deciding which method to use is up to each individual programmer. The first method will be most efficient and IMO easiest to comprehend. The second will generate less global variables and require less lines of code. If you are trying to avoid "over-kill" Method #1 cannot be beaten.

Upvotes: 1

LF-DevJourney
LF-DevJourney

Reputation: 28529

try this, check the live demo

$result = [];
foreach($array as $v)
{
$max = max(array_column($v, 'gamesCount'));
    $result = array_merge($result, array_filter($v, function($value)use($max){return $value['gamesCount'] == $max;}));
}
var_dump($result);

Upvotes: 1

Related Questions