如何使用Lodash将父数组的isActive属性传递给嵌套子数组的每个元素
现有代码的核心问题
你写的逻辑没有拿到预期结果,主要是三个硬伤:
- 参数结构错误:
_.assign(task, parent.isActive)写法不对,_.assign需要传入带可枚举属性的源对象,直接传布尔值的parent.isActive根本不会给friend对象挂上isActive字段,等价于空合并操作 - 循环结果丢失:你用
_.forEach遍历父节点时,内层_.map生成的friend数组会被forEach直接丢弃,不会拼成最终需要的扁平结构 - 冗余内存损耗:你提前用
_.pick生成的firstRound数组,在大数据量场景下会额外占一份内存,完全可以跳过这步直接处理原始数据
性能最优的实现方案
处理这类嵌套结构,遍历到每一个friend节点是不可避免的(毕竟要给每个节点挂载属性),但可以通过减少中间数组生成、减少无效对象拷贝来最大化性能,直接用_.flatMap一步实现:
const result = _.flatMap(legitTask, (task) => { const currentActive = task.isActive; return task.friends.map(friend => ({ ...friend, isActive: currentActive })); });
针对超大数据量的场景,如果业务允许直接修改原数据对象(不需要保留原friend对象的不可变状态),可以进一步降低内存开销:
const result = _.flatMap(legitTask, (task) => { const currentActive = task.isActive; // 直接在原friend对象上挂载属性,省去新对象的生成开销 return task.friends.map(friend => { friend.isActive = currentActive; return friend; }); });
原有思路的修正版本
如果你确实需要保留之前生成firstRound中间数组的步骤,只需要把循环逻辑改对即可:
let firstRound = _.map(legitTask, task =>{ return _.pick(task, ['isActive', 'friends']); }); // 用flatMap替代forEach,自动收集所有内层map的结果 const result = _.flatMap(firstRound, parent => { return _.map(parent.friends, friend => // 修正assign的参数,正确传入isActive属性 _.assign(friend, { isActive: parent.isActive }) ); });
_.flatMap本身就是为「遍历数组每一项,把每一项返回的数组合并成最终一维数组」的场景设计的,比你自己初始化空数组、手动push每一层结果的性能更高,完全不会存在你担心的多层循环拖慢速度的问题。
内容的提问来源于stack exchange,提问作者napi15
相关产品推荐
相关产品推荐

