PHP 8.0 中 usort 仅排序不去重;二维数组去重需先序列化再 array_unique 或用字段组合键手动去重,因 array_unique 默认不支持二维数组。

PHP 8.0 中,usort 本身只负责排序,不处理去重;要去除二维数组的重复项,需在排序后配合 array_unique 或自定义逻辑。但注意:array_unique 默认对二维数组**不生效**(它只比较一维值或字符串),所以必须配合 SPL 或序列化/哈希等手段实现真正去重。
✅ 步骤一:用 usort 按指定键排序
假设你有一个用户数组,想按 age 升序排:
$users = [
['name' => 'Alice', 'age' => 30],
['name' => 'Bob', 'age' => 25],
['name' => 'Charlie', 'age' => 30],
['name' => 'David', 'age' => 25]
];
使用 usort(PHP 7.4+ 支持箭头函数,8.0 完全兼容):
usort($users, fn($a, $b) => $a['age'] <=> $b['age']);
此时数组已按 age 升序排列(相同 age 的顺序由原数组位置决定,稳定排序)。
立即学习“PHP免费学习笔记(深入)”;
✅ 步骤二:去除二维数组重复(关键!)
直接 array_unique($users) 会返回原数组(无效果),因为 PHP 默认用 string 比较,而数组无法转为唯一字符串。正确做法有以下两种常用方式:
- 方式1:用 array_map + serialize + array_unique + unserialize(简单直接,适合数据量不大)
$serialized = array_map('serialize', $users);
$unique_serialized = array_unique($serialized);
$users_unique = array_map('unserialize', $unique_serialized);
- 方式2:用 array_column + array_keys + 自定义比较(推荐用于大数组或需精确字段去重)
例如:只根据 name 和 age 联合去重(忽略其他键):
$seen = [];
$users_unique = [];
foreach ($users as $item) {
$key = $item['name'] . '|' . $item['age']; // 或用 md5(serialize([$item['name'], $item['age']]))
if (!isset($seen[$key])) {
$seen[$key] = true;
$users_unique[] = $item;
}
}
✅ 合并成一行链式写法(可读性稍低,但紧凑)
如果你追求简洁,可封装为函数:
function sortAndDedupe(array $arr, callable $comparator, string $dedupeKey = null): array
{
usort($arr, $comparator);
if ($dedupeKey) {
$seen = [];
return array_filter($arr, function($item) use ($dedupeKey, &$seen) {
$key = is_array($dedupeKey)
? implode('|', array_map(fn($k) => $item[$k], $dedupeKey))
: $item[$dedupeKey];
if (isset($seen[$key])) return false;
$seen[$key] = true;
return true;
});
}
// 全字段去重(序列化方式)
return array_values(
array_map('unserialize',
array_unique(array_map('serialize', $arr))
)
);
}
// 使用示例:
$users = sortAndDedupe($users, fn($a, $b) => $a['age'] <=> $b['age'], 'name');
⚠️ 注意事项
不要依赖 array_unique($arr, SORT_REGULAR) —— 它在 PHP 8.0 对关联二维数组仍不可靠,官方文档明确说明其行为“未定义”;
避免用 json_encode 做 key,因浮点、null、顺序敏感等问题易出错;
若数组含对象或资源,序列化会失败,需先转换为纯数组;
性能敏感场景建议用 foreach + 手动 key 判断,比序列化快 3–5 倍(实测千级数据)。



















