php 7.2 去除含浮点数的二维数组重复项需规避精度误差和多维限制:推荐预处理浮点字段后序列化去重,或用容差比较的手动循环、唯一键提取、排序后相邻去重四种方案。

PHP 7.2 去除含浮点数的二维数组重复项,关键在于避免浮点数直接比较导致的精度误差(如 0.1 + 0.2 !== 0.3),同时绕过 array_unique() 对多维数组原生不支持的限制。不能依赖简单序列化+去重后反序列化,因为浮点数在序列化前后可能因内部表示差异被误判为不同;也不能用 == 或 === 直接比较子数组——浮点字段哪怕值相等,顺序或键名稍有不同也会失败。
用 serialize + array_unique(需预处理浮点字段)
这是最常用且兼容 PHP 7.2 的方案,但必须先对浮点数做标准化处理,防止微小误差破坏序列化一致性:
- 遍历每个子数组,识别出所有浮点类型字段(例如
'price'、'score') - 将这些浮点值四舍五入到指定小数位(如
round($val, 6)),再强制转为字符串或保留为 float ——关键是保证相同语义的浮点数生成完全一致的序列化结果 - 再执行
array_map('serialize', $arr)→array_unique(...)→array_map('unserialize', ...) - 最后用
array_values()重置索引,确保数字键连续
用自定义循环 + 浮点安全比较
适合数据量不大、需严格控制比较逻辑的场景。核心是替换 in_array($item, $unique, true) 中的全等判断,改用逐字段比对,并对浮点字段启用容差比较:
- 定义一个辅助函数
floatEqual($a, $b, $epsilon = 1e-9),当abs($a - $b) 时返回 <code>true - 遍历原始数组,对每个
$item,手动检查$unique中是否存在「结构相同且所有浮点字段满足容差、其余字段全等」的子数组 - 推荐按键名顺序遍历子数组的
foreach ($item as $k => $v),遇到浮点类型(is_float($v))则调用floatEqual,否则用=== - 该方法不依赖序列化,无不可序列化类型风险,但性能随数据量增长明显下降
用 array_column 提取主键(适用于有唯一标识字段)
如果二维数组中存在天然唯一字段(如 'id')或可构造唯一组合(如 'user_id' . '_' . round($row['amount'], 2)),可跳过浮点比较难题:
- 先用
array_column($arr, 'id')提取 ID 列,或用array_map构建带四舍五入浮点的复合键 - 对该键数组调用
array_keys(array_flip(...))去重(array_flip自动覆盖重复键) - 再用
array_intersect_key($arr, array_flip($deduped_keys))精准保留对应行 - 此法最快最稳,但前提是业务上允许以某字段(或其加工结果)作为去重依据
用 usort + 相邻去重(稳定且规避浮点陷阱)
先统一排序,再线性扫描去重,能彻底避免浮点比较的随机性,也无需序列化开销:
- 使用
usort($arr, function($a, $b) { ... })对子数组排序:对每个键依次比较,浮点字段用floatEqual或round($a[$k], 6) round($b[$k], 6) - 排序后,重复项必然相邻。新建空数组,遍历排序后数组,仅当当前项与前一项「所有字段均等价」(浮点走容差,其余走全等)时才跳过
- 该方式时间复杂度 O(n log n),比纯循环更高效,且结果有序,适合后续分页或展示
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











