如何将嵌套对象按内部键重组?有无替代forEach的Lodash实现方案
对象按内部键重组的优化实现
需求示例
我们需要将如下结构的对象a转换为对象b:
const a = { 'pt-BR': { food: 'Comida', blue: 'Azul' }, 'en-US': { food: 'Food', blue: 'Blue' }, }; // 目标结构 const b = { food: { 'pt-BR': 'Comida', 'en-US': 'Food' }, blue: { 'pt-BR': 'Azul', 'en-US': 'Blue' }, };
初始实现
你当前的实现使用嵌套forEach循环:
Object.entries(a).forEach(([lang, translations]) => { Object.entries(translations).forEach(([word, translation]) => { b[word] = { ...b[word], [lang]: translation }; }); });
优化方案
1. 原生JavaScript(无显式forEach)
可以使用嵌套reduce实现更函数式的转换,完全避免显式forEach循环:
const b = Object.entries(a).reduce((acc, [lang, translations]) => { return Object.entries(translations).reduce((innerAcc, [word, translation]) => { innerAcc[word] = { ...(innerAcc[word] || {}), [lang]: translation }; return innerAcc; }, acc); }, {});
如果觉得嵌套reduce不够直观,也可以用单reduce结合对象展开的方式,逻辑更紧凑:
const b = Object.entries(a).reduce((acc, [lang, translations]) => { Object.entries(translations).forEach(([word, translation]) => { acc[word] = { ...acc[word], [lang]: translation }; }); return acc; }, {});
此方案无需提前声明空对象b,代码闭环性更强。
2. Lodash工具库实现
Lodash提供了更贴合对象结构转换的工具函数,以下两种方案都能高效完成需求:
方法一:使用_.transform
_.transform专门针对对象/数组的结构转换设计,逻辑更清晰:
const b = _.transform(a, (result, translations, lang) => { _.forEach(translations, (translation, word) => { result[word] = _.assign({}, result[word], { [lang]: translation }); }); }, {});
方法二:使用_.reduce + _.merge
利用_.merge自动合并对象的特性,代码最简洁:
const b = _.reduce(a, (acc, translations, lang) => { return _.merge(acc, _.mapValues(translations, val => ({ [lang]: val }))); }, {});
总结
如果项目已引入Lodash,推荐_.reduce+_.merge的方案,代码最精简;如果只用原生JS,嵌套reduce或单reduce的方案都能满足需求,且优化了初始实现的代码结构。
内容的提问来源于stack exchange,提问作者richardaum
相关产品推荐
相关产品推荐

