javascript去重需先清洗后过滤,剔除null、undefined、空白字符串、伪值及格式异常数据,再用filter预筛+set去重;对象去重应基于清洗后的唯一键(如id),避免引用比较。

在 JavaScript 中去重时剔除脏数据,核心思路是:**先清洗、再过滤**。不能只靠 Set 或 filter + indexOf 等简单去重逻辑,因为脏数据(如空字符串、null、undefined、全空格字符串、非数字的“伪数字”、非法日期格式等)若不提前识别并排除,可能被当作有效值参与去重,甚至污染结果。
明确“脏数据”的常见类型和清洗规则
不同业务场景下“脏数据”定义不同,但常见需剔除的包括:
-
空值类:
null、undefined、NaN -
空白类:纯空白字符串(
''、' '、'\t\n') -
伪值类:字符串
'null'、'undefined'、'NaN'(注意不是原始值,而是字符串字面量) -
格式异常类:手机号含字母、邮箱缺 @ 符号、日期字符串无法被
new Date()解析且非空 -
类型错位类:期望是数字,但值为字符串
'abc'或空数组[]
清洗 + 去重的一体化写法(推荐)
用 filter 预筛 + Set 去重,是最简洁可靠的方式。例如处理用户输入的手机号列表:
const rawPhones = ['13812345678', '', ' 13987654321 ', 'abc', null, '13812345678', '13987654321'];
const cleanAndUniquePhones = rawPhones
.filter(item => {
// 类型检查 + 字符串标准化 + 格式校验
if (typeof item !== 'string') return false;
const trimmed = item.trim();
if (!trimmed) return false;
// 简单手机号正则(11位数字,以1开头)
return /^1[3-9]\d{9}$/.test(trimmed);
})
.map(item => item.trim()) // 统一清理空格
.filter((item, index, arr) => arr.indexOf(item) === index); // 去重(或直接 [...new Set(...)])
// 结果:['13812345678', '13987654321']
封装可复用的清洗去重函数
针对不同字段,可抽象出带校验器的通用函数:
function uniqueByRule(arr, validator, keyFn = x => x) {
const seen = new Set();
return arr.filter(item => {
if (!validator(item)) return false;
const key = keyFn(item);
if (seen.has(key)) return false;
seen.add(key);
return true;
});
}
// 使用示例:去重并过滤非法邮箱
const emails = ['a@b.com', ' ', 'invalid-email', 'A@B.COM', 'a@b.com'];
const validUniqueEmails = uniqueByRule(
emails,
email => typeof email === 'string' && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email),
email => email.trim().toLowerCase() // 忽略大小写
);
// → ['a@b.com']
注意深比较与引用类型处理
若数组元素是对象,不能直接用 Set 去重(引用不同即视为不同)。此时需结合清洗 + 序列化键(如 JSON.stringify)或自定义唯一标识(如 id 字段):
const users = [
{ id: 1, name: '张三', phone: ' 138...' },
{ id: 2, name: '李四', phone: null },
{ id: 1, name: '张三丰', phone: '138...' }, // 重复 id,但其他字段不同
];
const cleanUsers = users
.filter(u => u && typeof u === 'object' && u.id && typeof u.id === 'number')
.filter((u, i, arr) => arr.findIndex(v => v.id === u.id) === i); // 按 id 去重
关键点在于:脏数据必须在去重前被 filter 拦截;去重依据(key)本身也应经过清洗(如转小写、去空格),否则形似神异的数据仍会残留。不复杂但容易忽略。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











