I have 2 arrays where they have some common id
values, but the keys for these id
keys differ slightly.
$comps = [
[
'c_id' => '123',
'status' => 'active'
],
[
'c_id' => '456',
'status' => 'destroyed'
],
[
'c_id' => '789',
'status' => 'active'
]
];
$rests = [
[
'r_id' => 123,
'extra' => 'some extra info for r_id 123'
],
[
'r_id' => 456,
'extra' => 'some extra info for r_id 456'
]
];
My objective here is to return all entries of the $rests
array that have corresponding entries within the $comps
array that have both matching ID values and a status => active
.
How can one achieve this?
I have seen and used array_uintersect()
in the past, however I can't seem to get this to work in the desired way.
CodePudding user response:
You can achive this with a nested foreach loop.
$matches = [];
foreach ($rests as $rest) {
foreach ($comps as $comp) {
if ($rest['r_id'] === $comp['c_id'] && $comp['status'] === 'active') {
$matches[] = $rest;
}
}
}
print_r($matches);
Output
Array
(
[0] => Array
(
[r_id] => 123
[extra] => some extra info for r_id 123
)
)
CodePudding user response:
Here is the array_uintersect()
implementation with the two rules.
This is a good choice because PHP optimizes the comparisons by using a sorting algorithm under the hood.
Code: (Demo)
var_export(
array_uintersect(
$comps,
$rests,
fn($a, $b) =>
[$a['c_id'] ?? $a['r_id'], ($a['status'] ?? 'active') === 'active']
<=>
[$b['c_id'] ?? $b['r_id'], ($b['status'] ?? 'active') === 'active']
)
);
With outdated PHP: (Demo)
var_export(
array_uintersect(
$comps,
$rests,
function($a, $b) {
return [$a['c_id'] ?? $a['r_id'], ($a['status'] ?? 'active') === 'active']
<=>
[$b['c_id'] ?? $b['r_id'], ($b['status'] ?? 'active') === 'active'];
}
)
);
I don't think that it's shameful to pre-filter the $comps
array. (Demo)
var_export(
array_uintersect(
array_filter($comps, function($row) { return $row['status'] === 'active'; }),
$rests,
function($a, $b) {
return ($a['c_id'] ?? $a['r_id'])
<=>
($b['c_id'] ?? $b['r_id']);
}
)
);
If interested in a brute force nested loop approach, then avoid doing useless cycles by conditionally breaking and continuing. I mean, think about it, why bother looping on the rests array if the given comps array can be disqualified early. Furthermore, after you make an id match and push the data into the result array, stop the inner loop. (Demo)
$result = [];
foreach ($comps as $comp) {
if ($comp['status'] !== 'active') {
continue;
}
foreach ($rests as $rest) {
if ($rest['r_id'] == $comp['c_id']) {
$result[] = $rest;
break;
}
}
}
var_export($result);