Reputation: 469
Is there a fast way to compare two arrays, where the second array contains all the keys from the first, but also has additional keys?
For example, given the two arrays below, I would want the final two elements from the first array as they do not exist on the second:
$input = [
[
'firstName' => 'Paula',
'lastName' => 'Fisher',
'companyName' => 'Ankunding-Braun'
],
[
'firstName' => 'Elliot',
'lastName' => 'Roob',
'companyName' => 'Feeney PLC'
],
[
'firstName' => 'Jammie',
'lastName' => 'Morar',
'companyName' => 'Pollich PLC'
],
[
'firstName' => 'Tyrell',
'lastName' => 'Mills',
'companyName' => 'Oberbrunner, Kulas and Rice'
],
[
'firstName' => 'Fred',
'lastName' => 'Johnson',
'companyName' => 'Pollich PLC'
],
[
'firstName' => 'Tyrell',
'lastName' => 'Bloggs',
'companyName' => 'BBC East'
],
];
$output = [
[
"id" => 1,
"firstName" => "Paula",
"lastName" => "Fisher",
"salutation" => "Prof.",
"email" => "[email protected]",
"phone" => "1-887-271-5742 x394",
"mobileNumber" => "1-558-612-4089 x45355"
],
[
"id" => 2,
"firstName" => "Elliot",
"lastName" => "Roob",
"salutation" => "Prof.",
"email" => "[email protected]",
"phone" => "+1-378-385-3633",
"mobileNumber" => "1-815-769-2297",
],
[
"id" => 3,
"firstName" => "Jammie",
"lastName" => "Morar",
"salutation" => "Mr.",
"email"=> "[email protected]",
"phone" => "(694) 767-1593 x5966",
"mobileNumber" => "204-991-3292",
],
[
"id" => 4,
"firstName" => "Tyrell",
"lastName" => "Mills",
"salutation"=> "Mrs.",
"email" => "[email protected]",
"phone" => "462-385-0569 x22876",
"mobileNumber" => "532-369-9039"
]
];
As a little bit of context, I am trying to return all records that do not exist on the database (checking first name, last name and company name). If there's a faster way of doing this using the database that would be great, but I can't think of anything myself, so I've returned the records that are found, and now want to remove the found records from the searched array - therefore leaving me with the records that do not exist.
Upvotes: 0
Views: 38
Reputation: 49188
To find the searches not found in the results, you can:
// I can't "query", this is for demonstration based on the question data.
// The assumption here is that this is a hydrated to array resultset from a
// Doctrine ORM query, but it should work for any array comparison of this
// sort.
$filtered = array_filter($output, function($row) use($input) {
return array_reduce($input, function($carry, $compare) use($row) {
return $carry || (
$compare['firstName'] == $row['firstName']
&& $compare['lastName'] == $row['lastName']
// Uncomment this if you want, and have, companyName to compare.
// && $compare['companyName'] == $row['companyName']
);
});
});
$notfound = array_filter($input, function($search) use($filtered) {
// Note the negation here, this uses array_reduce() to tell us when
// there's a "hit", we're looking for $search rows with no "hit".
return !array_reduce($filtered, function($carry, $row) use($search) {
return $carry || (
$search['firstName'] == $row['firstName']
&& $search['lastName'] == $row['lastName']
// Uncomment this if you want, and have, companyName to compare.
// Note that the hydrated resultset needs to account for this.
// && $compare['companyName'] == $row['companyName']
);
});
});
Upvotes: 1