array_unique
Removes duplicate values from an array, keeping the first occurrence and its key.
array_unique(array $array, int $flags = SORT_STRING): array- Added in PHP 4.0.1
Parameters
| Parameter | Type | Description |
|---|---|---|
$array | array | The input array. It is not modified. |
$flagsoptional | int= SORT_STRING | How values are compared: SORT_STRING (default, compares as strings), SORT_REGULAR (normal comparison without changing types), SORT_NUMERIC, or SORT_LOCALE_STRING. |
Return value
arrayA copy of the array with duplicate values removed. Keys of the retained elements are preserved.
Errors
Throws a TypeError if $array is not an array. With the default SORT_STRING, values that cannot be cast to string (such as arrays or objects without __toString) raise an error.
Changelog
- PHP 7.2With SORT_STRING the result is now built by adding unique elements to a new array rather than removing elements from a copy, which can produce different numeric indexes than earlier versions.
array_unique() returns the array with repeated values dropped. The first occurrence of each value survives along with its key; later duplicates are discarded.
When to reach for it
Deduplicating tags, email addresses, or ids collected from several sources is the everyday use. If you need to know how many times each value appeared rather than just the distinct set, array_count_values() gives you that in one pass.
What trips people up
Two things, both of which produce bug reports.
First, keys are preserved, so the result has gaps: ['a','b','a'] becomes [0 => 'a', 1 => 'b'], but ['a','a','b'] becomes [0 => 'a', 2 => 'b']. That is no longer a list, and json_encode() will emit a JSON object instead of an array. Wrap the result in array_values() whenever it is going to be serialised or iterated by index.
Second, the default comparison is string-based: two values are equal when (string)$a === (string)$b. So 10, '10' and 10.0 all collapse into one, and every object without __toString() raises an error. Pass SORT_REGULAR to compare values as they are — though be aware that loose comparison then makes 0, false and null group together.
For a large list of scalars, array_keys(array_flip($arr)) is often much faster.
Example
When to use it
- Deduplicate a tag list assembled from several sources before saving it.
- Collapse a list of ids gathered in a loop into a distinct set for a single IN query.
- Strip repeated email addresses out of a pasted recipient list.
Frequently asked questions
Does array_unique preserve keys?
Yes, it keeps the key of the first occurrence of each value, which leaves gaps in a numerically indexed array. Wrap the result in array_values() to get a clean list.
Is array_unique case-sensitive?
Yes. 'PHP' and 'php' are different values under every flag. Lowercase the values yourself, or key an array by the normalised form, to deduplicate case-insensitively.
Why does array_unique treat 10 and '10' as the same value?
The default SORT_STRING flag compares values after casting them to strings. Pass SORT_REGULAR to compare them without changing types.
More examples
SORT_REGULAR versus the default
Both flags collapse 1 with '1' and 1.5 with '1.5', leaving 1, 1.5 and 'one'. The last call shows the SORT_REGULAR trap: loose comparison treats 0, false and null as equal, so only int(0) survives.
<?php
$mixed = [1, '1', 1.5, '1.5', 'one'];
print_r(array_unique($mixed));
print_r(array_unique($mixed, SORT_REGULAR));
var_dump(array_unique([0, false, null], SORT_REGULAR));Counting instead of deduplicating
array_unique tells you the distinct answers were yes and no. array_count_values tells you yes appeared 3 times and no 2 times, in a single pass.
<?php
$votes = ['yes', 'no', 'yes', 'yes', 'no'];
print_r(array_unique($votes));
print_r(array_count_values($votes));Case-insensitive deduplication
array_unique is always case-sensitive, so it would keep both spellings of Ann. Keying by the lowercased address and using ??= keeps the first spelling seen while collapsing the duplicates.
<?php
$emails = ['[email protected]', '[email protected]', '[email protected]'];
$byLower = [];
foreach ($emails as $e) {
$byLower[strtolower($e)] ??= $e;
}
print_r(array_values($byLower));
Discussion