Reputation: 11
I have below two arrays:
$a = [
['code' => '123', 'name' => 'ABC',],
['code' => '456', 'name' => 'XYZ',],
];
$b = [
['code' => '123', 'name' => 'ABC', 'price' => '34'],
['code' => '456', 'name' => 'PQR', 'price' => '56'],
['code' => '456', 'name' => 'XYZ', 'price' => '90'],
];
I want to create a third array where in the combination of code and name matches, like this:
$c = [
['code' => '123', 'name' => 'ABC', 'price' => '34'],
['code' => '456', 'name' => 'XYZ', 'price' => '90'],
]
I don't want the second row of $b
to be retained since the combination of code and name in that row does not match with a row in array $a
Upvotes: -2
Views: 89
Reputation: 48031
Your data structures are not built well for the required comparison. It would be easier if both of the arrays had "compound keys" instead of indexes. I mean, if the rows in the arrays looked like '123_ABC' => ['code' => '123', 'name' => 'ABC',]
then making direct key-based comparisons would be a breeze.
Using what you have and with the intention of reducing the total iterations over the arrays, I recommend nested loops with early breaks in the inner loop as soon as a match is found.
Code: (Demo)
$whiteList = [
['code' => '123', 'name' => 'ABC',],
['code' => '456', 'name' => 'XYZ',],
];
$pricedList = [
['code' => '123', 'name' => 'ABC', 'price' => '34'],
['code' => '456', 'name' => 'PQR', 'price' => '56'],
['code' => '456', 'name' => 'XYZ', 'price' => '90'],
['code' => '456', 'name' => 'GHI', 'price' => '70'],
];
$result = [];
foreach ($pricedList as $pricedRow) {
foreach ($whiteList as $whiteRow) {
if ($whiteRow['code'] === $pricedRow['code'] && $whiteRow['name'] === $pricedRow['name']) {
$result[] = $pricedRow;
continue 2; // no reason to keep iterating inner loop after match is found
}
}
}
var_export($result);
Or more elegantly, use array_intersect_assoc()
with each row of the whitelist array. (Demo)
$result = [];
foreach ($pricedList as $pricedRow) {
foreach ($whiteList as $whiteRow) {
if ($whiteRow === array_intersect_assoc($whiteRow, $pricedRow)) {
$result[] = $pricedRow;
continue 2; // no reason to keep iterating inner loop after match is found
}
}
}
var_export($result);
Output (from either snippet):
array (
0 =>
array (
'code' => '123',
'name' => 'ABC',
'price' => '34',
),
1 =>
array (
'code' => '456',
'name' => 'XYZ',
'price' => '90',
),
)
Upvotes: 1
Reputation: 48031
By unconditionally purging the potential price element before making full row comparisons inside of array_uintersect()
, you can filter the array with price data by the array without prices.
Code: (Demo)
var_export(
array_uintersect(
$pricedList,
$whiteList,
function($a, $b) {
unset($a['price'], $b['price']);
return $a <=> $b;
}
)
);
Upvotes: 0