filter本身不能直接去重,需结合indexOf或Set判断首次出现;indexOf法保持顺序、兼容性好;Set法更灵活,支持大小写/空格处理及对象字段去重;相邻比较法仅适用于已排序数组,不适用于搜索历史。

用 filter 本身不能直接去重,它只负责“筛选”,不改变数组结构或自动识别重复项。要去掉搜索历史里的重复关键词,得结合其他方法(比如 indexOf 或 Set)来判断是否为首次出现。
用 filter + indexOf 保留首次出现的关键词
核心思路:对每个元素,检查它在原数组中第一次出现的位置是否等于当前索引。只有首次出现时才保留。
适合场景:保持原始顺序,且关键词是字符串或基本类型。
- 写法简洁,兼容性好(支持所有浏览器)
- 原数组不变,返回新数组
- 注意大小写敏感,如需忽略,先统一转小写再比较
示例:
立即学习“Java免费学习笔记(深入)”;
const history = ['apple', 'banana', 'apple', 'cherry', 'banana']; const uniqueHistory = history.filter((item, index) => history.indexOf(item) === index); // 结果:['apple', 'banana', 'cherry']
用 filter 配合 Set 记录已见项(更灵活)
如果需要更复杂的判断逻辑(比如忽略空格、大小写、或按对象字段去重),可以用一个外部 Set 记录已处理过的值,再在 filter 中检查。
- 适合处理清洗后的关键词,例如
item.trim().toLowerCase() - 可复用同一 Set 实现多条件去重
- 注意不要在多次调用中复用同一个 Set,否则会漏掉新数据
示例(忽略大小写和首尾空格):
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
const history = ['Apple', ' banana ', 'APPLE', 'Cherry'];
const seen = new Set();
const uniqueHistory = history.filter(item => {
const key = item.trim().toLowerCase();
if (seen.has(key)) return false;
seen.add(key);
return true;
});
// 结果:['Apple', ' banana ']
如果关键词是对象(如 { keyword: 'xxx', time: ... })
不能直接用 indexOf 或默认 Set,因为对象引用不同即视为不同。需基于某个字段(如 keyword)去重。
- 推荐用 Map 或 Set 存储已见的 keyword 字符串
- filter 内部提取字段做判断,保持原对象结构
- 避免修改原始对象,确保纯函数行为
示例:
立即学习“Java免费学习笔记(深入)”;
const history = [
{ keyword: 'js', time: 1710000000 },
{ keyword: 'javascript', time: 1710000100 },
{ keyword: 'js', time: 1710000200 }
];
const seenKeywords = new Set();
const uniqueHistory = history.filter(item => {
if (seenKeywords.has(item.keyword)) return false;
seenKeywords.add(item.keyword);
return true;
});
// 结果保留第一个 'js' 对象
不推荐:仅用 filter 做去重(常见误区)
有人误以为 filter((v, i) => arr[i] !== arr[i-1]) 能去重,这其实只跳过**相邻重复项**,不是真正去重。比如 ['a','b','a'] 不会被处理掉第二个 'a'。
这种写法只适用于**已排序数组的相邻去重**,和搜索历史这种无序、随机插入的场景不匹配。
不复杂但容易忽略细节,关键在明确“重复”的定义,再选对辅助手段配合 filter。

















