如何更简洁实现JavaScript嵌套对象过滤,替代两次for of循环?
嵌套对象过滤简化实现问题
我在过滤这类嵌套对象时遇到了问题,肯定有更简单的实现方法。
原始对象结构
theObject = { "a": [{"val":"","date":2},{"val":20,"date":2}], "b": [{"val":"","date":2}], "c": [{"val":"10","date":1},{"val":20,"date":2},{"val":"30","date":3}] } myFilteredObject = {}
过滤规则
从theObject中移除不符合条件的冗余数据,规则如下:
- 仅保留每个数组的最后一个对象进行校验,校验规则为:
val != ""或date < 2 - 校验通过的键保留,值为仅包含最后一个对象的数组
- 最终将有效数据存入
myFilteredObject
预期结果示例
myFilteredObject = { "a": [{"val":20,"date":2}], "c": [{"val":"30","date":3}] }
当前实现代码
我目前的实现使用了两次遍历Object.entries的for...of循环,代码如下:
let theObject = { "a": [{"val":"","date":2},{"val":20,"date":2}], "b": [{"val":"","date":2}], "c": [{"val":"10","date":2},{"val":20,"date":2},{"val":"30","date":1}] } let myFilteredObject = {} const filterFunction = function(){ // 移除所有不符合条件的数据 for(let [key, value] of Object.entries(tab)){ if(value[value.length-1].val !== "" || value[value.length-1].date < 1){ myFilteredObject[key] = tab[key] } // 仅保留每个数组的最后一个对象 for(let [key, value] of Object.entries(myFilteredObject)){ myFilteredObject[key].splice(0, myFilteredObject[key].length -1) } } } filterFunction() console.log("result",myFilteredObject)
问题
请问有没有更简洁的方式实现上述需求?
解决方案
注:原实现中的tab属于笔误,实际应为要遍历的原始对象theObject
可以直接用Object.fromEntries搭配一次遍历实现,只需要对每个键对应的数组取最后一项校验,符合条件就组装成新的键值对返回即可,代码更简洁也避免了嵌套循环:
const filterObject = (origin) => { return Object.fromEntries( Object.entries(origin) // 先过滤符合校验规则的键 .filter(([_, arr]) => { const lastItem = arr.at(-1); return lastItem.val !== "" || lastItem.date < 2; }) // 再组装成仅保留最后一项的数组结构 .map(([key, arr]) => [key, [arr.at(-1)]]) ) } // 调用示例 const myFilteredObject = filterObject(theObject); console.log(myFilteredObject);
优化点
- 避免了原实现中的嵌套循环,时间复杂度降低为O(n)(n为对象的键数量)
- 不会修改原对象的数组(原实现用
splice会直接修改原数组),无副作用 - 逻辑拆分清晰,可读性更高
内容的提问来源于stack exchange,提问作者Thib Right
相关产品推荐
相关产品推荐

