如何在JavaScript/React中移除对象数组重复项?现有方案失效求助
对象数组去重问题解决方案
问题背景
参考了对象数组去重的相关方案但未找到适配场景的方法,当前在向iconsProps数组添加新元素时,尝试避免重复项的逻辑失效,需要在useEffect中实现批量去重逻辑,当iconsProps长度大于visibleAnnotations长度时执行。
现有代码与类型定义
添加元素时的失败尝试
const idsExistsOnIconProps = iconsProps.some((id) => ids.includes(id.toString())); const existingIndex = iconsProps.findIndex( (iconProp) => iconProp.coordinates.left === element.offsetLeft && iconProp.coordinates.top === element.offsetTop && !idsExistsOnIconProps ); if (existingIndex === -1) { const newIconCoordinates: AnnotationIconProps[] = [ ...iconsProps, { coordinates: { top: element.offsetTop, left: element.offsetLeft, }, content: { header: contentHeader, text: contentText, }, typeOfAnnotation: hasMultipleAnnotations ? "multiple" : isSystemNotification ? "system" : "single", ids, }, ]; setIconProps(newIconCoordinates); }
类型定义参考
export type AnnotationIconProps = { coordinates: { top: number; left: number; }; content: { header: string; text: string; }; typeOfAnnotation: AnnotationType; ids: (string | number)[]; };
目标:useEffect中实现去重
useEffect(() => { if (iconsProps.length > visibleAnnotations.length) { // 需要实现的去重函数 } }, [iconsProps]);
解决方案
1. 修复添加元素时的去重逻辑(从源头避免重复)
原逻辑存在两个核心问题:
idsExistsOnIconProps遍历对象而非id,判断逻辑错误- 将全局条件混入
findIndex的元素判断中,导致逻辑混乱
修正后的逻辑(可根据业务需求调整重复判定规则):
// 判断是否存在坐标完全相同的元素 const hasDuplicateCoord = iconsProps.some(icon => icon.coordinates.left === element.offsetLeft && icon.coordinates.top === element.offsetTop ); // 判断是否存在ids数组有交集的元素 const hasOverlappingIds = iconsProps.some(icon => icon.ids.some(id => ids.includes(id.toString())) ); // 仅当无重复时添加新元素(可根据业务选择判定条件) if (!hasDuplicateCoord && !hasOverlappingIds) { setIconProps(prev => [...prev, { coordinates: { top: element.offsetTop, left: element.offsetLeft }, content: { header: contentHeader, text: contentText }, typeOfAnnotation: hasMultipleAnnotations ? "multiple" : isSystemNotification ? "system" : "single", ids, }]); }
2. 实现useEffect中的批量去重
当需要事后批量清理重复项时,可通过生成唯一标识过滤重复元素:
useEffect(() => { if (iconsProps.length > visibleAnnotations.length) { // 生成唯一键:坐标拼接 + 排序后的ids拼接(避免ids顺序不同导致误判) const uniqueMap = new Map(); iconsProps.forEach(icon => { const coordKey = `${icon.coordinates.top}-${icon.coordinates.left}`; const sortedIds = [...icon.ids].sort().join(','); const uniqueKey = `${coordKey}-${sortedIds}`; // 仅保留首次出现的元素 if (!uniqueMap.has(uniqueKey)) { uniqueMap.set(uniqueKey, icon); } }); // 将Map转换为数组并更新状态 setIconProps(Array.from(uniqueMap.values())); } }, [iconsProps, visibleAnnotations]);
规则自定义说明
- 若坐标相同即判定重复:仅用
coordKey作为唯一标识 - 若ids数组完全相同即判定重复:仅用
sortedIds作为唯一标识 - 可根据业务需求调整唯一键的生成规则,适配不同的重复判定逻辑
内容的提问来源于stack exchange,提问作者Alvaro Silva
相关产品推荐
相关产品推荐

