Signature
array_count_values(array $array): arrayPurpose
array_count_values() turns a list of values into a frequency table. Each distinct value from the input becomes a key in the result, and the matching element is the number of times that value appeared. It is the quickest way to answer questions such as "how many times does each tag, status or word occur?" without writing a manual loop.
Signature
Parameters and defaults
The function takes a single parameter, $array, and it has no optional parameters. Only integer and string elements can be counted, because only those types can be array keys. Array keys of the input are ignored; only the values matter.
Return value and failure cases
The function returns an array whose keys are the distinct values and whose values are integer counts. Keys appear in the order in which each value first occurs in the input. An empty input array produces an empty array.
The function does not throw an exception for unsupported elements. Instead, it raises an E_WARNING for every element that is neither a string nor an integer (floats, booleans, null, arrays and objects), skips that element, and keeps counting the rest. If you run it with a strict error handler, those warnings can be turned into exceptions by your own code.
Example 1: counting words
Splitting a string and counting the pieces is the classic use case.
$text = "red blue red green blue red";
$counts = array_count_values(explode(" ", $text));
echo json_encode($counts, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";{"red":3,"blue":2,"green":1}
The result lists red first because it appeared first in the input, followed by blue and green.
Example 2: key normalization and case
The values become array keys, so PHP's normal key rules apply. A string that looks like a canonical decimal integer, such as "8", is converted to the integer key 8. That means the string "8" and the integer 8 are counted together. Comparison is also case-sensitive, so "PHP" and "php" are separate entries.
$values = ["PHP", "php", "PHP", "8", 8];
$counts = array_count_values($values);
echo json_encode($counts, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";{"PHP":2,"php":1,"8":2}
If you want case-insensitive counting, normalize the values first, for example with array_map('strtolower', $values) when the data is ASCII text.
Example 3: unsupported values are skipped
This example installs a temporary error handler so the warnings can be counted instead of printed. The integer 1 and the string "a" are counted. The float, null and boolean are skipped, which produces three warnings.
$warnings = 0;
set_error_handler(function (int $severity, string $message) use (&$warnings): bool {
$warnings++;
return true;
});
$counts = array_count_values([1, 2.5, "a", null, true]);
restore_error_handler();
echo json_encode(["counts" => $counts, "warnings" => $warnings], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";{"counts":{"1":1,"a":1},"warnings":3}
Edge cases
- Numeric strings that are not canonical. A value such as
"02"or"1.5"stays a string key, so"02"is not merged with2. - Empty input. You get an empty array back, with no warning.
- Input keys. Associative or sparse input arrays work the same way as lists, since only values are inspected.
- Sorting the result. The output is in first-seen order, not sorted by count. Use
arsort()oruasort()if you need the most frequent value first. - Mixed content. One bad element does not stop the call, but the output silently omits it, so check your data if totals look too low.
Common mistakes
- Passing floats or booleans and expecting them to be counted. Convert them to strings first if you need them, for example with
array_map('strval', $values), but note that this changes howtrue,falseandnullappear ("1",""and""). - Expecting case-insensitive results.
"Apple"and"apple"are different keys unless you normalize them. - Assuming keys keep their original type. Canonical integer strings become integer keys, which matters if you later use strict comparisons on the keys.
- Counting nested data. Arrays and objects cannot be keys, so rows of records must be reduced to a scalar field first, often with
array_column(). - Using it when you need positions. This function only tallies frequency. If you need to know where each value occurred, build the result with a loop.
Related functions
count()counts all elements in an array or aCountableobject.array_unique()removes duplicate values rather than counting them.array_values()returns all values of an array with fresh numeric keys.count_chars()returns information about the bytes used in a string.
Recap
array_count_values() takes an array of integers and strings and returns a map from each distinct value to its frequency, ordered by first appearance. Keys follow PHP's array key rules and comparison is case-sensitive. Elements of other types raise an E_WARNING and are skipped, so prepare your data before counting.
Tested examples
$text = "red blue red green blue red";
$counts = array_count_values(explode(" ", $text));
echo json_encode($counts, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
{"red":3,"blue":2,"green":1}
$values = ["PHP", "php", "PHP", "8", 8];
$counts = array_count_values($values);
echo json_encode($counts, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
{"PHP":2,"php":1,"8":2}
$warnings = 0;
set_error_handler(function (int $severity, string $message) use (&$warnings): bool {
$warnings++;
return true;
});
$counts = array_count_values([1, 2.5, "a", null, true]);
restore_error_handler();
echo json_encode(["counts" => $counts, "warnings" => $warnings], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
{"counts":{"1":1,"a":1},"warnings":3}