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' );
Advertisement
Answer
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);