如何高效过滤含重复属性的JavaScript数组?(数据量超500)
问题描述
我有如下结构的JavaScript数组:
const foodsList = [ { foodOrigin: "Padang", foodName: "Nasi Padang", originCode: "PDN" }, { foodOrigin: "Padang", foodName: "Gulai", originCode: "PDN" }, { foodOrigin: "Padang", foodName: "Rendang", originCode: "PDN" }, { foodOrigin: "Palembang", foodName: "Pempek", originCode: "PLG" }, { foodOrigin: "Palembang", foodName: "Tekwan", originCode: "PLG" }, { foodOrigin: "Yogyakarta", foodName: "Gudeg", originCode: "YKT" } ];
希望将该数组过滤为仅保留每个唯一originCode对应的foodOrigin与originCode的数组,目标结果如下:
const filteredFoodsList = [ { foodOrigin: "Padang", originCode: "PDN" }, { foodOrigin: "Palembang", originCode: "PLG" }, { foodOrigin: "Yogyakarta", originCode: "YKT" } ];
目前我通过以下双重循环的方式实现了需求,但实际数据量超过500条,请问是否有更简洁高效的实现方法?
const filteredFoodsList = []; for (let i = 0; i < foodsList.length; i++) { if (i === 0) { filteredFoodsList.push({ originCode: foodsList[i].originCode, foodOrigin: foodsList[i].foodOrigin }); } let isExist = false; for (let j = 0; j < filteredFoodsList.length; j++) { if (foodsList[i].originCode === filteredFoodsList[j].originCode) { isExist = true; } } if (!isExist) { filteredFoodsList.push({ originCode: foodsList[i].originCode, foodOrigin: foodsList[i].foodOrigin }); } }
高效实现方案
你的双重循环时间复杂度为O(n²),数据量超过500条时性能会明显下降。下面几种方法均为O(n)时间复杂度,更简洁高效:
方法1:使用Map去重
利用Map的键唯一性,遍历数组时以originCode为键存储目标对象,最后提取Map的所有值:
const map = new Map(); foodsList.forEach(item => { if (!map.has(item.originCode)) { map.set(item.originCode, { foodOrigin: item.foodOrigin, originCode: item.originCode }); } }); const filteredFoodsList = Array.from(map.values());
方法2:结合Set与filter
先用Set记录已出现的originCode,再通过filter筛选首次出现的项,最后转换为目标结构:
const seenCodes = new Set(); const filteredFoodsList = foodsList.filter(item => { if (!seenCodes.has(item.originCode)) { seenCodes.add(item.originCode); return true; } return false; }).map(({ foodOrigin, originCode }) => ({ foodOrigin, originCode }));
方法3:使用reduce一步完成
用reduce同时实现去重和结构转换,逻辑更紧凑:
const filteredFoodsList = Array.from( foodsList.reduce((acc, { foodOrigin, originCode }) => { acc.set(originCode, { foodOrigin, originCode }); return acc; }, new Map()).values() );
这三种方法仅需遍历数组一次,在数据量大时性能优势显著,同时代码更简洁易读,维护成本更低。
内容的提问来源于stack exchange,提问作者a fan of fried rice
相关产品推荐
相关产品推荐

