
本文介绍使用 PHP 对二维数组按前两列值进行分组、统计各组合出现次数,并以“键 值x次数”格式输出的完整实现,涵盖 array_reduce 高效分组、浮点数字符串安全处理及结果遍历格式化技巧。
本文介绍使用 php 对二维数组按前两列值进行分组、统计各组合出现次数,并以“键 值x次数”格式输出的完整实现,涵盖 `array_reduce` 高效分组、浮点数字符串安全处理及结果遍历格式化技巧。
在数据聚合场景中,常需基于多个字段(如类别 + 数值)对记录分组并统计频次,最终生成可读性高的格式化字符串。原始代码虽能实现基础计数,但嵌套逻辑冗长、可读性差,且未完成最终输出。以下提供更简洁、健壮、符合 PHP 最佳实践的解决方案。
✅ 推荐方案:array_reduce 分组 + 双层遍历格式化
我们利用 array_reduce 一次性构建嵌套关联数组:外层以第一列(如 'FA')为键,内层以第二列数值的字符串形式(强制转为 (string)$value[1])为键,值为出现次数。该方式避免手动初始化、减少条件判断,语义清晰且性能良好。
$array = [
['FA', 12.9],
['FA', 12.9],
['FB', 12.2],
['FC', 12.3],
['FA', 12.9],
['FB', 12.9],
['FA', 12.4],
];
// 步骤1:双维度分组计数
$grouped = array_reduce($array, function ($carry, $item) {
[$category, $value] = $item;
$key = (string)$category;
$valStr = (string)$value; // 关键:浮点数转字符串避免精度/类型歧义
if (!isset($carry[$key])) {
$carry[$key] = [];
}
if (!isset($carry[$key][$valStr])) {
$carry[$key][$valStr] = 0;
}
$carry[$key][$valStr]++;
return $carry;
}, []);
// 步骤2:按原始输入顺序(或任意顺序)遍历并格式化输出
foreach ($grouped as $category => $values) {
foreach ($values as $valStr => $count) {
echo "$category $valStr" . "x$count\n";
}
}
输出结果:
FA 12.9x3 FA 12.4x1 FB 12.2x1 FB 12.9x1 FC 12.3x1
⚠️ 注意事项:
- 浮点数处理:直接用
$value[1]作数组键可能导致精度问题(如12.9在内部存储为12.899999...),务必显式转换为字符串(string)$value[1]。- 顺序保证:PHP 数组保持插入顺序,因此外层
foreach按首次出现的 category 顺序遍历;若需严格按原始数据顺序输出每条记录的首次出现位置,应额外维护索引映射。- 扩展性:此结构天然支持后续操作,如筛选
count > 1的重复项、导出 JSON 或渲染 HTML 表格。
✅ 替代方案(兼容旧版本 PHP):foreach + 引用优化
若项目限制无法使用匿名函数或需更高可读性,可用简化版 foreach:
$grouped = [];
foreach ($array as [$cat, $val]) {
$sVal = (string)$val;
if (!isset($grouped[$cat][$sVal])) {
$grouped[$cat][$sVal] = 0;
}
$grouped[$cat][$sVal]++;
}
// 格式化输出同上
该写法逻辑直白,性能与 array_reduce 版本几乎一致,且更易调试。
综上,推荐优先采用 array_reduce 方案——它将状态累积逻辑封装于高阶函数中,使主流程专注“做什么”而非“怎么做”,显著提升代码可维护性与表达力。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











