如何使用lodash以更简洁的函数式方式扁平化对象内的嵌套数组
我有如下 facebookResponseObject 对象,需要将其中值为数组类型的字段做扁平化处理。目前我使用reduce函数实现该需求,但想了解是否有更简洁的函数式写法可以解决这个问题。
输入示例
const facebookResponseObject = { account_currency: "xxx", campaign_name: "xxxxxxxx", account_name: "xxxxxxxx", adset_name: "xxxxxxxx", ad_name: "xxxxxxxx", reach: "xxxx", impressions: "xxxx", frequency: "xxxx", spend: "xxxx", cpm: "xxxx", inline_link_clicks: "xxxx", cost_per_inline_link_click: "xxxx", inline_link_click_ctr: "xxxx", clicks: "xxxx", cost_per_unique_click: "xxxx", cost_per_action_type: [ { action_type: "link_click", value: "xxxx" }, { action_type: "landing_page_view", value: "xxxx" }, { action_type: "post_engagement", value: "xxxx" }, { action_type: "page_engagement", value: "xxxx" }, { action_type: "lead", value: "xxxx" }, { action_type: "video_view", value: "xxxx" }, { action_type: "like", value: "xxxx" }, ], actions: [ { action_type: "link_click", value: "xxxx" }, { action_type: "landing_page_view", value: "xxxx" }, { action_type: "post_engagement", value: "xxxx" }, { action_type: "page_engagement", value: "xxxx" }, { action_type: "post_reaction", value: "xxxx" }, { action_type: "lead", value: "xxxx" }, { action_type: "post", value: "xxxx" }, { action_type: "comment", value: "xxxx" }, { action_type: "video_view", value: "xxxx" }, { action_type: "like", value: "xxxx" }, ], test_key: [ { action_type: "test1", value: "xxxx" }, { action_type: "test2", value: "xxxx" }, { action_type: "test3", value: "xxxx" }, { action_type: "test4", value: "xxxx" }, ], cpc: "xxxx", ctr: "xxxx", date_start: "xxxx-xx-xx", date_stop: "xxxx-xx-xx", account_id: "xxxxxxxx", };
现有转换函数
const formatResponse = _.reduce( facebookResponseObject, (acc, cur, key) => { if (_.isArray(cur)) { acc = { ...acc, ..._.chain(cur) .keyBy(obj => `${key}.${obj.action_type}`) .mapValues(v => v.value) .value(), }; } else { acc[key] = cur; } return acc; }, {}, );
预期输出结果
{ account_currency: 'xxx', campaign_name: 'xxxxxxxx', account_name: 'xxxxxxxx', adset_name: 'xxxxxxxx', ad_name: 'xxxxxxxx', reach: 'xxxx', impressions: 'xxxx', frequency: 'xxxx', spend: 'xxxx', cpm: 'xxxx', inline_link_clicks: 'xxxx', cost_per_inline_link_click: 'xxxx', inline_link_click_ctr: 'xxxx', clicks: 'xxxx', cost_per_unique_click: 'xxxx', 'cost_per_action_type.link_click': 'xxxx', 'cost_per_action_type.landing_page_view': 'xxxx', 'cost_per_action_type.post_engagement': 'xxxx', 'cost_per_action_type.page_engagement': 'xxxx', 'cost_per_action_type.lead': 'xxxx', 'cost_per_action_type.video_view': 'xxxx', 'cost_per_action_type.like': 'xxxx', 'actions.link_click': 'xxxx', 'actions.landing_page_view': 'xxxx', 'actions.post_engagement': 'xxxx', 'actions.page_engagement': 'xxxx', 'actions.post_reaction': 'xxxx', 'actions.lead': 'xxxx', 'actions.post': 'xxxx', 'actions.comment': 'xxxx', 'actions.video_view': 'xxxx', 'actions.like': 'xxxx', 'test_key.test1': 'xxxx', 'test_key.test2': 'xxxx', 'test_key.test3': 'xxxx', 'test_key.test4': 'xxxx', cpc: 'xxxx', ctr: 'xxxx', date_start: 'xxxx-xx-xx', date_stop: 'xxxx-xx-xx', account_id: 'xxxxxxxx' }
更精简的实现方案
1. 依赖Lodash的写法
逻辑拆分清晰,比原reduce写法少了分支判断和手动累加器维护:
const formatResponse = obj => ({ // 保留所有非数组属性 ..._.omitBy(obj, _.isArray), // 处理所有数组属性,拍平后合并 ..._.chain(obj) .pickBy(_.isArray) .flatMap((arr, key) => arr.map(item => [`${key}.${item.action_type}`, item.value])) .fromPairs() .value() })
2. 无依赖原生JS写法
不需要引入任何第三方库,兼容所有现代JS运行环境:
const formatResponse = obj => Object.fromEntries([ // 保留非数组字段 ...Object.entries(obj).filter(([_, val]) => !Array.isArray(val)), // 处理数组字段生成扁平化键值对 ...Object.entries(obj) .filter(([_, val]) => Array.isArray(val)) .flatMap(([key, arr]) => arr.map(item => [`${key}.${item.action_type}`, item.value])) ])
两种写法均为纯函数,输入输出与原实现完全一致,代码更加声明式,可读性更高。
内容的提问来源于stack exchange,提问作者xqcccccccccc
相关产品推荐
相关产品推荐

