
本文介绍一种高效方法:将多个单元素关联数组按其值分组,再统计每组中不同键(key)出现的次数,最终生成以原数组值为键、去重后键数量为值的新统计数组。
在实际开发中,我们常遇到类似这样的结构化数据:一个数组包含若干个单键值对的子数组(如 [1 => 7]),其中“值”代表类别(如商品ID、状态码等),“键”代表该类别下的某个标识(如用户ID、订单号等)。需求是——对每个类别值,统计其下不重复的标识总数,而非简单计数所有子数组。
例如,给定如下数据:
$values = [
[1 => 7], [2 => 7], [3 => 7], [4 => 7], [4 => 7],
[5 => 7], [5 => 7], [6 => 7], [1 => 8], [2 => 8],
];目标是得到:
[
7 => 6, // 键 1,2,3,4,5,6 → 共6个不同键
8 => 2 // 键 1,2 → 共2个不同键
]核心思路解析
关键在于双重映射:
- 第一步:以子数组的 value(如 7 或 8)为外层键,收集所有对应的 key(如 1, 2, 4, 5 等)到一个数组中;
- 第二步:对每个 value 对应的 key 数组执行 array_unique() 去重;
- 第三步:用 count() 统计去重后的 key 数量。
完整实现代码
7], [2 => 7], [3 => 7], [4 => 7], [4 => 7],
[5 => 7], [5 => 7], [6 => 7], [1 => 8], [2 => 8],
];
$items = []; // 用于暂存:$items[7] = [1,2,3,4,5,6], $items[8] = [1,2]
foreach ($values as $subArray) {
$val = reset($subArray); // 获取子数组的值(value)
$key = key($subArray); // 获取子数组的键(key)
$items[$val][] = $key; // 按值分组,追加对应键
}
// 去重每个分组内的键(避免重复计数同一标识)
$items = array_map('array_unique', $items);
// 统计每个分组去重后的键数量
$result = array_map('count', $items);
// 输出结果(PHP 7.4+ 推荐使用 var_export 或 print_r)
var_export($result);
// 输出:array (7 => 6, 8 => 2,)注意事项与优化建议
- ✅ reset() + key() 是安全组合:适用于单元素关联数组;若子数组可能为空,请先校验 !empty($subArray);
- ⚠️ 键类型兼容性:本方案支持数字键与字符串键,但若原始键含非标字符或空格,需确认业务是否允许;
- ? 性能提示:对于超大数据集(>10万项),可改用 isset() 判断代替 array_unique() 的全量去重,例如:
if (!isset($items[$val][$key])) { $items[$val][$key] = true; } $result[$val] = count($items[$val]); - ? 调试技巧:在 array_map('array_unique', $items) 前插入 print_r($items),可清晰查看分组中间态,便于验证逻辑正确性。
该方法逻辑清晰、无第三方依赖,适用于 PHP 5.4+,是处理此类“按值聚类→去重计数”场景的经典范式。










