如何过滤出数组对象中所有元素共有的嵌套KPI?
问题描述
我有一个名为allKpis的对象数组,生成该数组的代码如下:
for (let material of submission.materials) { const { docs } = await getDocs( query(collection(db, "materials"), where("name", "==", material.name)) ); const materialKpis = docs[0].data().kpis.map((kpi) => { return { kpis: kpi.id, value: kpi.value }; }); allKpis = [ ...allKpis, { material: material.name, kpis: materialKpis, }, ]; }
数组结构示例:
[ {"kpis": [{id: "A4yYU8r9hFxCgEDV77ps", value: 2}], "material": "Test Materiaal"}, {"kpis": [{id: "A4yYU8r9hFxCgEDV77ps", value: 2}, {id: "HhoomonFUYGVv4H4RTj3", value: 3}], "material": "Test Materiaal 2"} ]
每个数组元素包含material字段和嵌套的kpis数组,其中每个KPI对象包含id和value属性。
需要编写一个函数处理allKpis,仅保留所有元素中都存在的KPI(移除仅部分元素拥有的KPI),处理后的目标结果如下:
[ {"kpis": [{id: "A4yYU8r9hFxCgEDV77ps", value: 2}], "material": "Test Materiaal"}, {"kpis": [{id: "A4yYU8r9hFxCgEDV77ps", value: 2}], "material": "Test Materiaal 2"} ]
实现方案
分两步完成处理:
- 提取所有物料共有的KPI ID集合
- 过滤每个物料的KPI列表,仅保留共有ID对应的项
代码实现
function filterCommonKpis(allKpis) { // 收集每个物料的KPI ID集合 const kpiIdSets = allKpis.map(item => new Set(item.kpis.map(kpi => kpi.id))); // 计算所有集合的交集,得到全局共有的KPI ID let commonKpiIds = kpiIdSets[0]; for (let i = 1; i < kpiIdSets.length; i++) { commonKpiIds = new Set([...commonKpiIds].filter(id => kpiIdSets[i].has(id))); } // 过滤每个物料的KPI列表 return allKpis.map(item => ({ ...item, kpis: item.kpis.filter(kpi => commonKpiIds.has(kpi.id)) })); }
代码说明
- 用
Set存储每个物料的KPI ID,利用集合的高效查找特性简化交集计算 - 通过遍历所有物料的KPI ID集合,逐步筛选出所有物料都包含的ID
- 最后遍历原数组,对每个物料的KPI列表做过滤,只保留ID在共有集合中的项
使用示例
// 传入原数组得到处理后的结果 const processedKpis = filterCommonKpis(allKpis); console.log(processedKpis);
内容的提问来源于stack exchange,提问作者Bowis
相关产品推荐
相关产品推荐

