TL;DR: If your arrays have the same size and identical keys, then use foreach()
for best performance. If you prefer concise, functional code and only need loose comparisons, use array_diff_assoc()
. If you prefer functional code and need strict comparisons, then use array_filter()
.
This answer will use the following new sample data to clarify the required behavior:
$array1 = ['keepThis', 'remove', false, 'keep', 'save', 'delete'];
$array2 = ['hangOnto', 'remove', null, 'retain', 'keep', 'delete'];
Because the values at index [1]
in the arrays (remove
) are identical these values will not be stored in the clean arrays. The same is true for the elements with an index of [5]
(delete
). Although keep
is found in both arrays, the elements do not share the same indices/keys.
The correct result should be:
$clean1 = [0 => 'keepThis', 2 => false, 3 => 'keep', 4 => 'save'];
$clean2 = [0 => 'hangOnto', 2 => null, 3 => 'retain', 4 => 'keep'];
The asker's foreach()
loop enjoys the benefit of having the smallest time complexity because it only traverses the first array just one time. However, if the array might not have the same count or keyed elements, then that code risks generating Warnings at $array2[$key]
or not fully populating $clean2
.
array_diff_assoc()
offers a concise functional approach, but only implements loose comparisons (if it matters): (Demo)
var_export([
array_diff_assoc($array1, $array2),
array_diff_assoc($array2, $array1)
]);
Bad Result (because false
is loosely equal to null
):
[
[0 => 'keepThis', 3 => 'keep', 4 => 'save'],
[0 => 'hangOnto', 3 => 'retain', 4 => 'keep'],
]
You can try to overcome the PHP core algorithm for array_diff_uassoc()
, but this will either be unstable or prohibitively over-complicated.
array_filter()
is able to make strict comparisons and is not horribly verbose thanks to PHP7.4's arrow function syntax. (Demo)
var_export([
array_filter(
$array1,
fn($value, $index) => $array2[$index] !== $value,
ARRAY_FILTER_USE_BOTH
),
array_filter(
$array2,
fn($value, $index) => $array1[$index] !== $value,
ARRAY_FILTER_USE_BOTH
)
]);