Reputation: 664
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
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
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