假设我们有来自Api的一些嵌套和非规范化数据,我如何使用Ramda简化响应,以便它可以在前端应用程序中轻松使用。
转换此回复
{
articles: [
{
id: 1,
title: "Dagon",
tags: [{ id: 1, name: "old ones" }, { id: 2, name: "short story" }]
},
{
id: 2,
title: "Azathoth",
tags: [{ id: 1, name: "old ones" }, { id: 3, name: "novel" }]
},
{
id: 3,
title: "At the Mountains of Madness",
tags: [{ id: 4, name: "insanity" }, { id: 3, name: "novel" }]
}
]
}
至
{
articles: {
byId:{
1: { title: "Dagon", tags: [1, 2] },
2: { title: "Azathoth", tags: [1, 3] },
3: { title: "At the Mountains of Madness", tags: [3, 4] }
},
allIds:[1,2,3]
},
tags: {
byId:{
1: "old ones",
2: "short story",
3: "novel",
4: "insanity"
},
allIds:[1,2,3,4]
}
}
我可能会这样写:
const articles = R.pipe(
R.prop('articles'),
R.applySpec({
allIds: R.pluck('id'),
byId: R.pipe(
R.groupBy(R.prop('id')),
R.map(
R.pipe(
R.head,
R.evolve({ tags: R.pluck('id') }),
R.dissoc('id'),
),
),
),
}),
);
const tags = R.pipe(
R.prop('articles'),
R.pluck('tags'),
R.flatten,
R.uniqBy(R.prop('id')),
R.applySpec({
allIds: R.pluck('id'),
byId: R.pipe(
R.groupBy(R.prop('id')),
R.map(R.path([0, 'name'])),
),
}),
);
const normalize = R.applySpec({ tags, articles });
const data = {
articles: [
{
id: 1,
title: "Dagon",
tags: [
{ id: 1, name: "old ones" },
{ id: 2, name: "short story" },
],
},
{
id: 2,
title: "Azathoth",
tags: [
{ id: 1, name: "old ones" },
{ id: 3, name: "novel" },
],
},
{
id: 3,
title: "At the Mountains of Madness",
tags: [
{ id: 4, name: "insanity" },
{ id: 3, name: "novel" },
],
},
],
};
console.log('result', normalize(data));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
这很有趣,因为通常会遇到相反的问题:我已经从我希望在客户端上取消规范化的服务中规范化了数据。我可以看到这是如何产生的,但它与我的经历不同。
我可能会这样写:
const articles = pipe(
prop('articles'),
reduce((a, {id, title, tags}) => ({...a, [id]: {title, tags: pluck('id', tags)}}), {})
)
const tags = pipe(
prop('articles'),
pluck('tags'),
flatten,
reduce((a, {id, name}) => ({...a, [id]: name}), {})
)
const normalize = (resp, as = articles(resp), ts = tags(resp)) => ({
articles: {byId: as, ids: keys(as)},
tags: {byId: ts, ids: keys(ts)}
})
const resp = {articles:[{id:1,title:"Dagon",tags:[{id:1,name:"old ones"},{id:2,name:"short story"}]},{id:2,title:"Azathoth",tags:[{id:1,name:"old ones"},{id:3,name:"novel"}]},{id:3,title:"At the Mountains of Madness",tags:[{id:4,name:"insanity"},{id:3,name:"novel"}]}]};
console.log(normalize(resp))
<script src="https://bundle.run/[email protected]"></script><script>
const {pipe, prop, reduce, pluck, flatten, keys} = ramda </script>
reduce
中的tags
步骤可以被map(values), fromPairs
取代,但这感觉就像一个hack,因为它取决于标签中属性的顺序。
与您请求的输出的一个不同之处在于,我将标记ID保留为文章标记的原始顺序。因此article 3
有标签[4, 3]
而不是你的[3, 4]
。我认为这更有意义,因为标签可能有一些内在的排序,但显然如果你不喜欢它,你可以简单地添加一个sort
步骤。