Reputation: 5766
Need to eliminate from Array A arrays that key 'service_code' value doesn't exist on Array B. In the example, only 'SAF' exists on Array B. Have tried a variety of array_intersect functions with no luck. Instead of doing a loop, I believe there must be a method unknown to me to accomplish this. I can also invert Array B by removing array_keys if necessary.
Array A
Array
(
[1] => Array
(
[id] => 2
[service_name] => Carpet Cleaning
[type] =>
[category_name] => Household
[service_code] => SAF
[category_code] => AA
)
[2] => Array
(
[id] => 3
[service_name] => Floor Cleaning
[type] =>
[category_name] => Household
[service_code] => MHSAF
[category_code] => AA
)
[3] => Array
(
[id] => 4
[service_name] => Lawn Service
[type] =>
[category_name] => Landscape
[service_code] => GHF
[category_code] => AA
)
)
Array B
Array
(
[0] => SAF
[1] => SA
[2] => MM
[3] => METH
[4] => OTPA
[5] => OTP
[6] => CBT
[7] => SACA
[8] => TRC
[9] => REBT
)
Expected Result
Array
(
[1] => Array
(
[id] => 2
[service_name] => Carpet Cleaning
[type] =>
[category_name] => Household
[service_code] => SAF
[category_code] => AA
)
)
Upvotes: 0
Views: 90
Reputation: 71384
At the end of the day you will doing loops no matter what with those data structures, even if the "loop" is hidden within a function call like array_filter()
.
My number one suggestion would be to change Array B if possible so that you don't need to iterate it to see if a value in the array exists. A data structure like:
[
'SAF' => 1,
'SA' => 1,
...
]
You can achieve a data structure like this easily be executing array_flip()
on the array.
A structure where the keys contain the values you are looking for will let you do an O(1) lookup - instead of O(n) - for checking service codes from array A.
Your code could then look like:
$result = array_filter($array_a, function($item, $k) use ($array_b) {
return array_key_exists($item['service_code'], $array_b);
});
If you cannot change array b as described you would need to iterate Array B (which is what happens when you call in_array()
function) in the array_filter
operation:
$result = array_filter($array_a, function($item, $k) use ($array_b) {
return in_array($item['service_code'], $array_b);
});
The first solution would have a run time complexity of O(n) where n is number of elements in Array A.
The second solution would have a run time complexity of O(n*m) where m is number of elements of Array B (n is still number of elements in array A).
Since the second solution performs so poorly, you can optimize by using array_flip()
$service_code_keys = array_flip($array_b);
$result = array_filter(
$array_a,
function($item, $k) use ($service_code_keys) {
return array_key_exists($item['service_code'], $service_code_keys);
}
);
The would improve operational complexity to O(m + n) as you take a one time O(m) hit to iterate and flip Array B. Still this is much improved over the in_array()
solution.
Upvotes: 2
Reputation: 41810
Because service_code
is unique across array A, you can use array_column
to reindex array A using service_code
.
$array_a = array_column($array_a, null, 'service_code');
Then flip array B so that its values become keys
$array_b = array_flip($array_b);
Then you can use array_intersect_key
to get your result.
$result = array_intersect_key($array_a, $array_b);
Or all in one statement if you like:
$result = array_intersect_key(
array_column($array_a, null, 'service_code'), array_flip($array_b));
Upvotes: 0
Reputation: 54831
Your solution is array_filter
:
$filtered = array_filter(
$array1,
function($v) use ($array2) {
return in_array($v['service_code'], $array2);
}
);
Upvotes: 2