01 · THE IDEAREAD → TRY → LEARN
Arrays as sets
A set is a collection where each value counts once and order is irrelevant. PHP has no dedicated set type for plain values, so we usually treat an ordinary array as a set and compare two of them with array_diff() and array_intersect(). These functions are easy to call but have three behaviors you should plan for: they preserve keys, they keep duplicates, and they compare values as strings.
Difference: what is only on the left
array_diff($left, $right) returns the entries of $left whose values do not appear in any of the other arrays. Because the entries come straight from $left, their original keys survive. That means a result can have gaps in its keys, and json_encode() will then output an object rather than a list.
$left = ["a" => "green", "red", "blue", "red"];
$right = ["b" => "green", "yellow", "red"];
echo json_encode(array_diff($left, $right)), "\n";{"1":"blue"}
Only blue remains, and it keeps its key 1. The keys of $right never matter, only its values.
Intersection: what both sides share
array_intersect($a, $b) is the mirror image. It returns entries from the first array whose values also occur in the other arrays. Again the keys come from the first array. When you want a clean list, wrap the result in array_values(), which renumbers keys from zero.
$a = [5, 6, 7, 8];
$b = [6, 8, 9];
echo json_encode(array_intersect($a, $b)), "\n";
echo json_encode(array_values(array_intersect($a, $b))), "\n";{"1":6,"3":8}
[6,8]
The first line shows the preserved keys 1 and 3. The second shows the reindexed list. Reindexing is a choice you make on purpose, not something these functions do for you.
Values are compared as strings
Two values count as equal when their string forms are identical. So 1 and "1" match, and so do 4 and 4.0, because (string) 4.0 is "4". This is convenient for lists of integers and strings, but it means you should not use these functions on arrays of arrays, which cannot be converted to strings.
$left = [1, 2, 3, "4"];
$right = ["1", 4.0];
echo json_encode(array_diff($left, $right)), "\n";{"1":2,"2":3}
The values 1 and "4" are removed, leaving 2 and 3 with their original keys.
Duplicates and order
A true set has no repeats, but array_diff() and array_intersect() keep every repeated entry from the first array that passes the test. If $left contains 3 twice and 3 is not on the right, both copies appear in the difference. To normalize, apply array_unique() and then array_values(). If a caller needs a stable order, finish with sort(). Sorting is what makes the output deterministic and easy to test, since two inputs holding the same values in different orders then produce identical results.
A reliable pipeline for a clean set result is therefore:
- Compute the difference or intersection.
- Remove duplicates with
array_unique(). - Renumber with
array_values(). - Sort with
sort().
Worked reasoning
Take [3, 1, 3, 2] and [2, 2, 5]. The difference from left to right is [3, 1, 3], which after deduplication and sorting becomes [1, 3]. The difference from right to left is [5]. The intersection is [2]. Notice that the right array has 2 twice, yet the shared value appears once in the final result because we deduplicate.
Exercise contract
Write compare_sets(array $left, array $right): array. Both arguments are lists of integers. Return an associative array with exactly three keys, in this order:
left_only: values present in$leftbut not in$rightright_only: values present in$rightbut not in$leftboth: values present in both arrays
Each of the three results must be a list with no duplicates, renumbered from zero and sorted ascending. Empty inputs and fully overlapping inputs must produce empty lists in the right places. Zero and negative numbers must work too, so be careful not to rely on truthiness.
A helper that normalizes one array, or a loop over the three results, keeps the function short and avoids repeating the same three steps.
Functions · Arrays · Types
- Find intersections and differences with intentional reindexing
- Implement and test a deterministic PHP 8.4 function