I have a contact array with a set of values which I need to update. I also have a contactChangeLog array that will save the diff between an existing and updated contact. Only the keys which get updated need to be saved to the log. So with 2 contact arrays:
$oldContact = array(
'name' => 'Joeahkd',
'address' => '123 Masjdhfin',
'city' => 'Spring',
'state' => 'CA',
'zip' => '90101',
);
$newContact = array(
'name' => 'Joe',
'address' => '123 Main St',
'city' => 'Springville',
'state' => 'CA',
'zip' => '90101',
);
I can use array_diff_assoc()...
$existing = array_diff_assoc($oldContact, $newContact);
$update = array_diff_assoc($newContact, $oldContact);
$diff = array('previous' => $existing, 'new' => $update);
print_r($diff);
However, I am iterating twice through each array and something I learned about big O notation tells me that isn't right. Is there a more algorithmically efficient way of returning the updated keys and both existing and updated values? The result should be:
$previous = array(
'name' => 'Joeahkd',
'address' => '123 Masjdhfin',
'city' => 'Spring'
);
$updated = array(
'name' => 'Joe',
'address' => '123 Main St',
'city' => 'Springville'
);
You can try array_filter
:
$updated = array();
$previous = array_filter($oldContact, function($v, $k) {
if ($v != $newContact[$k]) {
$updated[$k] = $newContact[$k];
return true;
}
return false;
}, ARRAY_FILTER_USE_BOTH);
array_filter
will return the keys/values from the input array if the callback function we specify returns true during each key/value iteration and those will be our $previous
. While we do the checking in the callback function we construct $updated
.
UPDATE:
Using array_filter
with array_intersect_key
even cut the code further:
$previous = array_filter($oldContact, function($v, $k) {
return ($v != $newContact[$k]);
}, ARRAY_FILTER_USE_BOTH);
$updated = array_intersect_key($newContact, $previous);