
本文详解如何在 php 中准确统计数组中各元素的出现频次,并仅提取出现次数大于 1 的重复项,生成键为元素值、值为出现次数的关联数组,避免常见逻辑错误。
本文详解如何在 php 中准确统计数组中各元素的出现频次,并仅提取出现次数大于 1 的重复项,生成键为元素值、值为出现次数的关联数组,避免常见逻辑错误。
在 PHP 开发中,快速识别并统计数组中重复元素的出现次数是一项高频需求。例如,给定数组 $arr = [1,2,2,2,4,5,5,5,8,9,10,2,5,9,10,10],我们期望得到仅包含重复项(即出现 ≥2 次)及其对应频次的关联数组:
Array
(
[2] => 4
[5] => 4
[9] => 2
[10] => 3
)✅ 推荐方案:使用 array_count_values() + array_filter()
最简洁、高效且可读性强的实现方式是组合使用 PHP 内置函数:
$arr = [1, 2, 2, 2, 4, 5, 5, 5, 8, 9, 10, 2, 5, 9, 10, 10];
// 步骤1:统计所有元素出现次数(返回完整频次表)
$allCounts = array_count_values($arr);
// 步骤2:过滤出仅重复出现(≥2次)的项
$duplicates = array_filter($allCounts, function($count) {
return $count > 1;
});
// 可选:确保键值顺序与原始数组中首次重复出现顺序一致(PHP 8.2+ 支持 array_key_first 等,但此处用 ksort 更通用)
ksort($duplicates); // 按键升序排列(如需保持原始顺序,可用 uksort 配合自定义索引映射)
print_r($duplicates);输出结果:
Array
(
[2] => 4
[5] => 4
[9] => 2
[10] => 3
)⚠️ 原始代码问题分析
你提供的嵌套循环逻辑存在以下关键缺陷:
立即学习“PHP免费学习笔记(深入)”;
-
计数重置时机错误:
else { $count = 1; }在内层比较不等时立即重置,导致跨不同元素的计数被干扰; -
重复键覆盖风险:
$duplicates[$arr[$j]] = $count;在未初始化时直接赋值,且$count并非针对当前元素独立累加; - 时间复杂度高:O(n²) 嵌套循环,对大数组性能极差;
-
逻辑耦合混乱:
in_array()判断与计数混杂,难以维护。
这类手动遍历易出错,应优先选用语义明确的内置函数。
? 替代方案:手动遍历(适用于学习或特殊场景)
若需手动实现(如面试考察基础逻辑),推荐单层 foreach + isset() 判断:
$arr = [1,2,2,2,4,5,5,5,8,9,10,2,5,9,10,10];
$counters = [];
foreach ($arr as $value) {
if (isset($counters[$value])) {
$counters[$value]++;
} else {
$counters[$value] = 1;
}
}
// 过滤重复项
$duplicates = array_filter($counters, fn($c) => $c > 1);
print_r($duplicates);? 提示:
isset()比array_key_exists()性能略优(因不检查null值),且在此场景下语义等价——我们只关心键是否存在并初始化计数。
? 注意事项与最佳实践
- ✅ 永远优先使用
array_count_values():它是 C 层实现,性能远超 PHP 循环,且代码零容错; - ✅
array_filter()默认保留原键,无需额外处理键名; - ❌ 避免对大数组使用
in_array()或多层嵌套循环; - ? 若需区分“重复项”与“全部频次”,明确分离两步操作(先全量统计,再按需过滤);
- ? 如需按出现频次降序排列:
arsort($duplicates);;如需按元素值升序:ksort($duplicates);。
掌握这一模式,不仅能精准解决重复统计问题,也为后续数据聚合、去重分析、排行榜生成等场景打下坚实基础。



















