javascript - 如何使用 Ramda 通过 id 查找和注入外来对象?
问题描述
我有一些对象集合,它们之间具有基本的一对多关系。我的目标是编写一个函数(或必要时可以组合的函数),以便将外部 ID 字段解析/注入到外部对象。
例如,我有以下对象:
const store = {
users: [
{
teamId: 'team-1',
name: 'user 1',
},
{
teamId: 'team-2',
name: 'user 2',
},
],
teams: [
{
id: 'team-1',
regionId: 'region-1',
name: 'Team 1',
},
{
id: 'team-2',
regionId: 'region-2',
name: 'Team 2',
}
],
regions: [
{
id: 'region-1',
name: 'Region 1',
},
{
id: 'region-2',
name: 'Region 2',
},
],
}
我的目标是将其解决为以下问题:
const users = [
{
teamId: 'team-1',
name: 'user 1',
team: {
id: 'team-1',
regionId: 'region-1',
region: {
id: 'region-1',
name: 'Region 1',
},
name: 'Team 1',
}
},
// ...and so on
]
我离解决第一级不远了:
const findObject = (collection, idField = 'id') => id => R.find(R.propEq(idField, id), R.prop(collection, store))
const findTeam = findObject('teams')
const findRegion = findObject('regions')
const inject = field => R.useWith(
R.merge,
[R.objOf(field), R.identity]
)
const injectTeam = R.useWith(
inject('team'),
[findTeam]
)
const injectRegion = R.useWith(
inject('region'),
[findRegion]
)
R.map(injectTeam('team-1'))(store.users)
但这对我来说太过分了,到目前为止,我只用 Ramda 做了更简单的事情。理想情况下,该解决方案将允许我以某种方式组合注入器功能,因此解决更深层次的问题是可选的。
解决方案
我正在使用 R.converge 提取users
并创建 and 的查找teams
,regions
然后通过从查找中users
替换teamId
为团队来映射 ,并在内部对该区域执行相同操作。
const { pipe, pick, map, indexBy, prop, converge, assoc, identity, flip, evolve } = R
// create a lookup of id -> object from teams and regions
const createLookup = pipe(
pick(['teams', 'regions']),
map(indexBy(prop('id')))
)
// add the value from the idPath in the lookup to the resultPath of the current object
const injectFromLookup = (idKey, lookup, resultKey) =>
converge(assoc(resultKey), [
pipe(
prop(idKey),
flip(prop)(lookup),
),
identity,
])
// extract users, create lookup, and map users to the required form
const inject = converge(
(users, lookup) => map(
pipe(
injectFromLookup('teamId', prop('teams', lookup), 'team'),
evolve({
team: injectFromLookup('regionId', prop('regions', lookup), 'region')
})
)
, users),
[prop('users'), createLookup],
)
const store = {"users":[{"teamId":"team-1","name":"user 1"},{"teamId":"team-2","name":"user 2"}],"teams":[{"id":"team-1","regionId":"region-1","name":"Team 1"},{"id":"team-2","regionId":"region-2","name":"Team 2"}],"regions":[{"id":"region-1","name":"Region 1"},{"id":"region-2","name":"Region 2"}]}
console.log(inject(store))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
推荐阅读
- java - 数组列表
在 Java 中,[€14,€55,€500] - node.js - 在 NodeJS 的方法内设置变量值
- javascript - 无法在后台和终止状态下触发推送通知
- vuejs2 - vue2数据更改不更新视图
- linux - Linux 多页边界和 cpu 段
- python - 验证准确率低但训练准确率高——keras imagedatagenerator flow_from_directory 分类分类
- java - 在一个巨大的集合中查找两个字符串的所有连接
- autocomplete - 占位符覆盖在浏览器中记住的用户名和密码
- javascript - JQuery:在解析 HTML 时防止加载图像
- vba - 自动刷新 Excel 工作表