You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 16:25:37