如何将带关联关系的对象数组重构为嵌套数组并避免重复?
问题
现有如下结构的对象数组:
[ { _id: "id1", metadata: { data: ["somedata1"], link: [] } }, { _id: "id2", metadata: { data: ["somedata2"], link: ["id2", "id3"] } }, { _id: "id3", metadata: { data: ["somedata3"], link: ["id2", "id3"] } }, { _id: "id4", metadata: { data: ["somedata4"] } } ]
其中link为可选字段,用于关联多个对象。需要将该数组转换为嵌套数组,合并所有存在关联关系的数据集,期望结果如下:
[ [ { _id: "id1", metadata: { data: ["somedata1"], link: [] } } ], [ { _id: "id2", metadata: { data: ["somedata2"], link: ["id2", "id3"] } }, { _id: "id3", metadata: { data: ["somedata3"], link: ["id2", "id3"] } } ], [ { _id: "id4", metadata: { data: ["somedata4"] } } ] ]
尝试遍历所有对象,但无法避免重复合并关联对象,当前代码如下:
const result = [] data.map(d => { if (!d.metadata.link?.length) result.push([d]) else result.push( data.getFiles.filter((item) => d.metadata.link.indexOf(item._id) !== -1) ) // but this would result in a duplicate array, as id2 and id3 have the same link content })
这段代码会因id2和id3的link内容相同而产生重复数组。
解决方案
核心思路是标记已处理的对象,避免重复加入结果集。具体实现代码如下:
const groupRelatedItems = (data) => { const processed = new Set(); // 记录已处理的_id const result = []; data.forEach(item => { if (processed.has(item._id)) return; // 获取当前item的关联id集合,默认包含自身 const relatedIds = new Set(item.metadata.link || [item._id]); // 确保自身id在关联集合中(处理link为空或不存在的情况) relatedIds.add(item._id); // 筛选出所有关联的对象 const group = data.filter(obj => relatedIds.has(obj._id)); // 标记分组内的所有对象为已处理 group.forEach(obj => processed.add(obj._id)); result.push(group); }); return result; }; // 测试数据 const data = [ { _id: "id1", metadata: { data: ["somedata1"], link: [] } }, { _id: "id2", metadata: { data: ["somedata2"], link: ["id2", "id3"] } }, { _id: "id3", metadata: { data: ["somedata3"], link: ["id2", "id3"] } }, { _id: "id4", metadata: { data: ["somedata4"] } } ]; console.log(groupRelatedItems(data));
关键说明
- 用
Set存储已处理的_id,判断和标记操作效率更高,时间复杂度为O(1)。 - 处理每个未被标记的对象时,先提取其关联的
_id集合,强制加入自身id,避免link为空或缺失时遗漏对象。 - 筛选出关联对象组成分组后,一次性标记分组内所有对象为已处理,后续遍历到这些对象时直接跳过,彻底避免重复分组。
内容的提问来源于stack exchange,提问作者user3142695
相关产品推荐
相关产品推荐

