如何以可扩展方式在JS中替换对象数组元素并求和?
可扩展的JS对象引用替换与求和方案
你的问题本质是依赖解析+数值聚合,原方案的循环遍历会重复处理引用,在大型对象场景下效率极低。下面给出基于记忆化缓存+递归依赖解析的方案,能高效适配数百个键、大量引用的场景。
核心思路
- 用缓存记录每个键已经解析好的最终数字数组,避免重复计算
- 递归解析每个键的数组:遇到字符串引用时,先解析引用的键,再合并其数字数组;遇到数字直接保留
- 所有引用解析完成后,对每个键的数字数组求和得到最终结果
代码实现
// 缓存已解析的键的数字数组,避免重复计算 const cache = new Map(); // 记录正在处理的键,用于检测循环引用 const processing = new Set(); /** * 解析单个键的所有引用,返回最终的数字数组 * @param {Object} obj - 输入对象 * @param {string} key - 当前要解析的键 * @returns {number[]} 解析后的数字数组 */ function resolveReferences(obj, key) { // 已缓存,直接返回结果 if (cache.has(key)) { return cache.get(key); } // 检测到循环引用,抛出错误 if (processing.has(key)) { throw new Error(`发现循环引用:${key}`); } processing.add(key); const currentItems = obj[key]; const resolvedNumbers = []; for (const item of currentItems) { if (typeof item === 'string') { // 递归解析引用的键,合并其数字数组 const refNumbers = resolveReferences(obj, item); resolvedNumbers.push(...refNumbers); } else { // 数字直接加入结果 resolvedNumbers.push(item); } } processing.delete(key); // 缓存当前键的解析结果 cache.set(key, resolvedNumbers); return resolvedNumbers; } /** * 计算所有键的数字和 * @param {Object} obj - 输入对象 * @returns {Object} 每个键对应数字和的结果对象 */ function calculateTotalSums(obj) { // 清空缓存,避免多次调用时的脏数据 cache.clear(); const result = {}; // 遍历所有键,依次解析并求和 for (const key of Object.keys(obj)) { const numbers = resolveReferences(obj, key); // 求和并包装为数组 result[key] = [numbers.reduce((total, num) => total + num, 0)]; } return result; }
使用示例
const inputObj = { '/': ['a', 'd', 10], a: ['e', 20], e: [30], d: [40] }; const output = calculateTotalSums(inputObj); console.log(output); // 输出: // { // '/': [ 100 ], // a: [ 50 ], // e: [ 30 ], // d: [ 40 ] // }
方案优势
- 高效可扩展:每个键仅解析一次,时间复杂度为O(N+E)(N是键的数量,E是所有引用的总数),面对数百个键的大型对象依然高效
- 自动处理嵌套引用:不管引用层级多深(比如A引用B,B引用C),递归会自动逐层解析
- 循环引用防护:通过
processing集合检测循环引用,避免无限递归导致的栈溢出 - 内存可控:缓存仅存储每个键的最终数字数组,不会产生额外冗余数据
内容的提问来源于stack exchange,提问作者DrBabol
相关产品推荐
相关产品推荐

