手机号去重不能直接用array_unique,必须先标准化:trim去空格、正则留数字、全角转半角;再用array_unique去重并保留首次键名,大数据量避免in_array线性查找。

array_unique 不能直接用于手机号去重
因为手机号常以字符串形式存在,而 array_unique 默认使用 SORT_STRING 比较,看似能用,但实际容易踩坑:比如带空格、括号、+86 前缀、全角数字、末尾换行符的手机号会被当成不同值,导致去重失效。
真正要做手机号去重,第一步永远是标准化——不是直接丢给 array_unique。
- 先用
trim()去首尾空白 - 用
str_replace()清掉常见干扰字符(' '、'-'、'('、')'、'+') - 对中文环境特别注意:用
mb_convert_kana($phone, 'n')把全角数字转半角 - 若需统一国内号码,可补
'86'前缀后取最后 11 位(但需谨慎判断原始格式)
标准化后再用 array_unique 最稳妥
标准化之后,再交给 array_unique 才有意义。它会保留第一次出现的原始键名,这对保留用户记录关联很重要。
示例:
$phones = ['138 1234-5678', '+86(138)12345678', '13812345678', '13812345678'];
$cleaned = array_map(function($p) {
$p = trim($p);
$p = mb_convert_kana($p, 'n'); // 全角转半角
$p = preg_replace('/[^\d]/', '', $p); // 只留数字
return $p;
}, $phones);
$unique = array_unique($cleaned);
// 结果:['13812345678'],键为 0(原数组第一个匹配项的键)
注意:array_unique 不会重排索引,如果后续要 json 输出或遍历,建议加 array_values($unique) 重置下标。
大数据量时慎用 in_array 手动去重
有人习惯写 foreach + in_array 实现去重,但对手机号数组尤其危险:
-
in_array('13812345678', $result)是线性查找,时间复杂度 O(n),10 万条数据就要做上万亿次比对 - PHP 的
in_array默认松散比较,'013812345678'和'13812345678'可能被误判相等 - 没做标准化就进循环,等于把脏数据反复比对,结果不可控
真要手写,至少用 isset($seen[$cleanedPhone]) 做哈希查表,O(1) 查找——但这已和 array_unique 底层逻辑一致,没必要重复造轮子。
关联数组中按手机号字段去重要用 array_column + array_unique
常见场景:从数据库取出的用户列表,每个元素是关联数组,含 'mobile' 字段。这时不能直接对整个数组调 array_unique,得先抽字段。
正确做法:
$users = [
['id' => 1, 'name' => '张三', 'mobile' => '13812345678'],
['id' => 2, 'name' => '李四', 'mobile' => ' 138-1234-5678 '],
['id' => 3, 'name' => '王五', 'mobile' => '13812345678'],
];
// 提取并清洗 mobile 列
$mobiles = array_column($users, 'mobile');
$cleanedMobiles = array_map(fn($m) => preg_replace('/[^\d]/', '', trim($m)), $mobiles);
$uniqueMobiles = array_flip(array_flip($cleanedMobiles)); // 快速去重,不关心键
// 再反查原始数组(保留首次出现的完整记录)
$seen = [];
$deduped = [];
foreach ($users as $user) {
$clean = preg_replace('/[^\d]/', '', trim($user['mobile']));
if (!isset($seen[$clean])) {
$seen[$clean] = true;
$deduped[] = $user;
}
}
这里关键点是:不能依赖 array_unique($users),它比较的是整个数组结构,不是单个字段;也不能只靠 array_unique($mobiles) 就完事,会丢失用户其他字段。
手机号去重真正的难点从来不在“去重函数选哪个”,而在于“怎么定义两个手机号算同一个”——这个规则必须在清洗阶段明确,且贯穿始终。一旦清洗逻辑和去重逻辑脱节,结果必然出错。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











