使用 lodash 展平对象内嵌套数组的功能方法?
Functional way to flatten nested array inside an object using 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'
}
您可以使用 flatMap
来迭代对象的条目。
- 不要触摸具有非数组值的条目
- 当有数组值时,将其元素迭代为return个新的键值对
- 作为密钥,将原始密钥与
action_type
- 作为一个值,取
value
属性
- 因为我们使用的是
flatMap
,所以我们确保不会 return 嵌套列表。
- 使用
Object.fromEntries
变回对象
const flatEntries = (obj) => Object
.entries(obj)
.flatMap(
([ k, v ]) => Array.isArray(v)
? v.map(a => [ `${k}.${a.action_type}`, a.value ] )
: [[k, v]]
);
const flattenObject = obj => Object.fromEntries(flatEntries(obj));
console.log(flattenObject(facebookResponseObject()));
function facebookResponseObject() { return {
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",
}; }
感谢您的帮助 @user3297291,我将对您的回答使用稍作修改的版本(使用 lodash)
const formatResponse = obj =>
_.chain(obj)
.toPairs()
.flatMap(([key, value]) =>
_.isArray(value)
? _.map(value, actionObj => [`${key}.${actionObj.action_type}`, actionObj.value])
: [[key, value]],
)
.fromPairs()
.value();
我有这个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'
}
您可以使用 flatMap
来迭代对象的条目。
- 不要触摸具有非数组值的条目
- 当有数组值时,将其元素迭代为return个新的键值对
- 作为密钥,将原始密钥与
action_type
- 作为一个值,取
value
属性
- 作为密钥,将原始密钥与
- 因为我们使用的是
flatMap
,所以我们确保不会 return 嵌套列表。 - 使用
Object.fromEntries
变回对象
const flatEntries = (obj) => Object
.entries(obj)
.flatMap(
([ k, v ]) => Array.isArray(v)
? v.map(a => [ `${k}.${a.action_type}`, a.value ] )
: [[k, v]]
);
const flattenObject = obj => Object.fromEntries(flatEntries(obj));
console.log(flattenObject(facebookResponseObject()));
function facebookResponseObject() { return {
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",
}; }
感谢您的帮助 @user3297291,我将对您的回答使用稍作修改的版本(使用 lodash)
const formatResponse = obj =>
_.chain(obj)
.toPairs()
.flatMap(([key, value]) =>
_.isArray(value)
? _.map(value, actionObj => [`${key}.${actionObj.action_type}`, actionObj.value])
: [[key, value]],
)
.fromPairs()
.value();