如何修改JS数组对象去重方法以支持嵌套键(如bounds)去重?
基于嵌套对象的数组去重问题
我找到一段可基于顶层多键对数组对象去重的代码:
const browsers = [ { os: "OS X", os_version: "Catalina", browser: "chrome", browser_version: "30.0" }, { os: "Windows", os_version: "7", browser: "chrome", browser_version: "40.0" }, { os: "Windows", os_version: "7", browser: "chrome", browser_version: "50.0" } ]; const makeUnique = (array = [], keys = []) => { if (!keys.length || !array.length) return []; return array.reduce((list, item) => { const hasItem = list.find(listItem => keys.every(key => listItem[key] === item[key]) ); if (!hasItem) list.push(item); return list; },[]); }; console.log(makeUnique(browsers, ["os", "os_version"]));
但我的数组包含嵌套的bounds对象,示例如下:
const tiles = [ { name: "pattern1", type: "jpg", size: 1024, bounds:{topleft_x: 45, topleft_y: 45, downright_x: -45, downright_y: -45}, }, { name: "pattern2", type: "jpg", size: 1024, bounds:{topleft_x: 90, topleft_y: 90, downright_x: 45, downright_y: 45}, }, { name: "pattern3", type: "jpg", size: 1024, bounds:{topleft_x: 45, topleft_y: 45, downright_x: -45, downright_y: -45}, }, //... ];
需要修改makeUnique方法,使其能基于嵌套的bounds子键进行去重,去除重复的bounds项。
解决方案
方案1:基于完整嵌套对象去重
如果需要整个bounds对象完全一致才判定为重复,可以添加深度比较对象的逻辑:
// 辅助函数:深度比较两个对象是否相等 const isEqual = (obj1, obj2) => { if (obj1 === obj2) return true; if (typeof obj1 !== 'object' || obj1 === null || typeof obj2 !== 'object' || obj2 === null) { return false; } const keys1 = Object.keys(obj1); const keys2 = Object.keys(obj2); if (keys1.length !== keys2.length) return false; for (const key of keys1) { if (!keys2.includes(key) || !isEqual(obj1[key], obj2[key])) { return false; } } return true; }; const makeUnique = (array = [], keys = []) => { if (!keys.length || !array.length) return []; return array.reduce((list, item) => { const hasItem = list.find(listItem => keys.every(key => { const val1 = item[key]; const val2 = listItem[key]; // 若是对象则深度比较,否则直接值比较 return typeof val1 === 'object' && val1 !== null ? isEqual(val1, val2) : val1 === val2; }) ); if (!hasItem) list.push(item); return list; }, []); }; // 使用方式:传入["bounds"]作为去重键 console.log(makeUnique(tiles, ["bounds"]));
方案2:基于嵌套键路径去重
如果需要灵活指定bounds内的具体子键(比如仅基于topleft_x和topleft_y去重),可以支持解析键路径:
// 辅助函数:根据键路径(如"bounds.topleft_x")获取对象值 const getValueByPath = (obj, path) => { return path.split('.').reduce((curr, key) => curr?.[key], obj); }; const makeUnique = (array = [], keys = []) => { if (!keys.length || !array.length) return []; return array.reduce((list, item) => { const hasItem = list.find(listItem => keys.every(key => getValueByPath(item, key) === getValueByPath(listItem, key)) ); if (!hasItem) list.push(item); return list; }, []); }; // 使用方式:传入bounds的子键路径数组 console.log(makeUnique(tiles, [ "bounds.topleft_x", "bounds.topleft_y", "bounds.downright_x", "bounds.downright_y" ]));
适用场景
- 方案1:适用于需要确保整个
bounds对象的所有键值都完全相同才去重的场景。 - 方案2:适用于只需匹配
bounds内指定子键即可去重的场景,灵活性更高。
内容的提问来源于Stack Exchange,提问作者Spiri
相关产品推荐
相关产品推荐

