
本文介绍一种简洁、函数式的方法,使用 filter() 与 findindex() 配合提取规则化字符串(如 "code1-code2-id-")中的 id 段,实现按 id 去重,保留每个 id 的首次出现项。
本文介绍一种简洁、函数式的方法,使用 filter() 与 findindex() 配合提取规则化字符串(如 "code1-code2-id-")中的 id 段,实现按 id 去重,保留每个 id 的首次出现项。
在处理结构化字符串数组时,常需依据某一段子字符串(如 ID)进行逻辑去重,而非整个字符串的完全匹配。例如,给定数组:
const links = [ "13989664-34-1-", "3588867-34-1-", "4757546-34-2-", "72469424-34-2-" ];
所有字符串均符合 code1-code2-id- 格式,其中 code2 固定(如 "34"),而 id(即第三个 - 分隔段)是去重的关键依据。目标是对每个唯一 id,仅保留其首次出现的完整字符串,最终得到 ["13989664-34-1-", "4757546-34-2-"]。
✅ 推荐解法:filter + findIndex(语义清晰、一行核心逻辑)
function getId(str) {
return str.split("-")[2]; // 提取第三段(索引为 2),即 id 部分
}
const uniqueLinks = links.filter((item, index) =>
links.findIndex(x => getId(x) === getId(item)) === index
);
console.log(uniqueLinks);
// → ["13989664-34-1-", "4757546-34-2-"]原理说明:
对每个元素 item,我们查找整个数组中第一个与其 id 相同的元素的索引;若该索引恰好等于 item 当前位置 index,说明它是该 id 的首次出现,应保留;否则跳过。此方法天然保证稳定性(始终保留首个),且无需额外状态变量或循环嵌套。
⚠️ 注意事项与优化建议
-
ID 提取要健壮:若字符串格式可能存在异常(如缺失 - 或长度不足),建议增强 getId:
function getId(str) { const parts = str.split("-"); return parts.length >= 3 ? parts[2] : ""; } -
性能考量:该方案时间复杂度为 O(n²),适用于中小规模数组(< 10k 项)。若数据量极大,可改用 Set + 单次遍历的 O(n) 方案:
const seenIds = new Set(); const uniqueLinks = links.filter(item => { const id = getId(item); if (seenIds.has(id)) return false; seenIds.add(id); return true; }); - 灵活性扩展:若需保留最后一个而非第一个匹配项,可将 findIndex 替换为 lastIndexOf(需先映射出 ID 数组)或改用 reduceRight。
✅ 总结
基于子字符串去重的核心在于抽象出可比键(key),再结合数组高阶方法实现声明式逻辑。filter + findIndex 组合兼具可读性、简洁性与正确性,是处理此类结构化字符串去重的推荐范式。实际开发中,建议将 getId 封装为纯函数,并根据数据质量决定是否添加边界校验。










