01 · THE IDEAREAD → TRY → LEARN
Why deduplicate?
Lists collect repeats easily: tags typed twice, IDs merged from two sources, words split from a sentence. Often you want each value once, in the order it first appeared. PHP's built-in tool for this is array_unique(). It is short to call, but two details trip people up: how it decides that two values are "the same", and what it does with array keys.
The signature
array_unique(array $array, int $flags = SORT_STRING): array
The function returns a new array and leaves the original untouched. With the default SORT_STRING flag, two elements count as equal when their string forms are identical. The first element that matches is kept, and later ones are dropped.
Rule 1: keys are preserved
When array_unique() drops an element, it does not renumber the survivors. Each survivor keeps its original key, string or integer. Study this example, where "green" and "red" each appear twice:
$input = ["a" => "green", "red", "b" => "green", "blue", "red"];
$result = array_unique($input);
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;{"a":"green","0":"red","1":"blue"}
The first "green" keeps key a. The first "red" keeps key 0, and "blue" keeps key 1. The later duplicates are removed.
Rule 2: gaps appear in list-like arrays
Suppose a plain list loses an element from the middle. The surviving keys are no longer 0, 1, 2, .... The gap matters as soon as you encode the array as JSON, because a list with gaps becomes a JSON object. It also matters when you later read $array[1] and expect the second item.
To get a clean list again, wrap the result in array_values(), which rebuilds sequential integer keys while keeping the order:
$input = [4, "4", "3", 4, 3, "3"];
$unique = array_unique($input);
$list = array_values($unique);
echo json_encode($unique), PHP_EOL;
echo json_encode($list), PHP_EOL;{"0":4,"2":"3"}
[4,"3"]
The first line shows keys 0 and 2 surviving. The second line shows a tidy list. Reindexing should be a deliberate choice: do it when you want a list, and skip it when the original keys carry meaning, such as the a key above.
Rule 3: equality is string-based
With the default flag, 4 and "4" are the same value. So are 1, 1.0 and true, because all three turn into the string "1". Strings that merely look similar, like "1" and "01", stay distinct because their text differs.
$values = [1, "1", 1.0, true, "01"];
var_dump(array_unique($values));array(2) {
[0]=>
int(1)
[4]=>
string(2) "01"
}
Only the first 1 and the string "01" remain. Casing also matters: "a" and "A" are different strings, so both survive. If you need case-insensitive deduplication, normalize the values first, for example by lowercasing, and decide which original spelling to keep.
Two more points to remember. The SORT_REGULAR flag compares with ordinary comparison rules, and the manual warns it can leave duplicates behind when numeric and non-numeric strings are mixed, so stay with the default unless you have a reason. And array_unique() is not meant for multidimensional arrays: nested arrays would need converting to a comparable form first.
Common mistakes
- Assuming the result is a list. After removals, keys can have gaps.
- Expecting
4and"4"to be treated as different values with the default flag. - Forgetting that comparison is case-sensitive for strings.
- Calling
array_unique()and ignoring the returned array. The original array is not modified.
Exercise contract
Write a function named dedupe_values that takes one array of scalar values and returns a list. The list must:
- Contain each value once, using the default string-based equality of
array_unique(). - Keep the first occurrence of each value and preserve first-seen order.
- Have sequential keys starting at
0, so it encodes as a JSON array.
An empty array must return an empty array. The checks compare the returned value, not printed output. Think about which two built-in functions you need and in which order to apply them.
Recap
array_unique() removes later values whose string form matches an earlier one, keeps the surviving keys, and returns a new array. Use array_values() afterwards when you need a list with fresh indexes. Remember that 4 and "4" collapse together, while "a" and "A" do not.
Functions · Arrays · Types
- Deduplicate values and deliberately normalize indexes
- Implement and test a deterministic PHP 8.4 function