php 8.3 中 array_unique 不能直接去重二维数组,因其内部不支持嵌套数组哈希比较,即使加 sort_regular 也会失效;必须通过 array_reduce 配合 json_encode(推荐加 json_force_object | json_unescaped_unicode | json_throw_on_error)构造唯一键实现去重,若需忽略键序则须先 ksort 标准化。

PHP 8.3 中用 array_reduce 对二维数组去重,核心思路是:把每个子数组“序列化”为唯一键(如 JSON 字符串或 implode 后的字符串),再用 array_reduce 累积构建一个以该键为索引、值为原数组项的关联结构,最后取值即可去重。
为什么不能直接用 array_unique?
array_unique 默认只支持一维数组(标量值);对二维数组会报 Warning 并返回原数组。即使加 SORT_REGULAR,PHP 8.3 仍不支持直接比较嵌套数组——因为数组不可哈希,无法作为键或用于内部去重逻辑。
用 array_reduce + 序列化键实现去重
关键在于构造一个稳定、可比、无歧义的唯一标识。推荐用 json_encode($item, JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE),它能保持键序、处理中文、避免浮点精度干扰(相比 serialize() 更轻量且跨平台)。
示例代码:
$data = [
['id' => 1, 'name' => 'Alice'],
['id' => 2, 'name' => 'Bob'],
['id' => 1, 'name' => 'Alice'], // 重复
['name' => 'Alice', 'id' => 1], // 键序不同 → JSON 编码后不同 → 视为不同项(注意!)
];
$unique = array_values(
array_reduce(
$data,
function ($carry, $item) {
$key = json_encode($item, JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE);
if (!isset($carry[$key])) {
$carry[$key] = $item;
}
return $carry;
},
[]
)
);
print_r($unique); // 输出 3 个元素(前两个 + 最后一个,中间重复被跳过)
若需忽略键顺序(如 ['a'=>1,'b'=>2] ≡ ['b'=>2,'a'=>1])
此时 JSON 编码不再可靠。应先标准化子数组:对键排序后再编码。
- 用
ksort($item)强制按键名升序排列 - 再
json_encode(..., JSON_FORCE_OBJECT) - 注意:ksort 会修改原数组引用,如需保留原始数据,应先
$normalized = $item; ksort($normalized);
性能与注意事项
该方法时间复杂度 O(n),空间略高(额外存一份键映射)。适用于中小规模数据(几千条以内)。若数据量极大,建议改用数据库 DISTINCT 或 SplFixedArray + 自定义哈希函数。
特别提醒:
- 浮点数字段慎用 JSON 编码(如
0.1 + 0.2 !== 0.3可能导致看似相同实则编码不同的 key) - 含 null、资源、闭包、对象的数组无法 JSON 编码,需提前过滤或换用
serialize()(但更慢、不易读) - PHP 8.3 支持
JSON_THROW_ON_ERROR,建议加上防止静默失败:json_encode(..., JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR)
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











