用另一个 object 的详细信息填充 object
Populate object with detail from another object
我有两个项目:
列表:
[{
"key": "A",
...optionalAprops
}, {
"key": "C",
...optionalCProps
}]
Collection:
{
"A": {
...detailAprops
},
"B": {
...detailBprops
},
"C": {
...detailCprops
}
}
如何使用 Ramda.js 或函数式样式,使用 Collection 中的详细信息填充 List,已映射通过它的键?
结果应该像
[{
"key": "A",
...optionalAprops,
...detailAprops
}, {
"key": "C",
...optionalCprops,
...detailCprops
}]
我现在拥有的是
var populate = R.curry(function(coll, item) {
return R.merge(item, R.props(R.props('key', item), coll));
});
var result = R.map(populate(Collection))(List);
populate
函数在我看来非常 un-functional,因为它仍然传递状态。有没有更简洁的方法来完成相同的任务,使用 Ramda.js?
步骤细分为
- 迭代列表项
- 在项目中取
key
- 在 Collection 和
key
中查找详细信息 object
- 合并回项目
我认为将状态保持在您想要的位置的最简单方法是将 map
调用移动到您的函数中:
var populate = R.curry(function(coll, list) {
return R.map(function(item) {
return R.merge(item, R.prop(R.prop('key', item), coll))
}, list);
});
populate(Collection, List);
// or `populate(Collection)` to create a function that accepts a List
(请注意,我将 R.props
替换为 R.prop
。我认为这只是一个打字错误;否则您会包含各种可能不需要的键。)
可能有一些方法可以让这个免分,但它最终可能会变得更丑陋。也许不是;我没试过。但我认为无积分只有在它使代码更具可读性时才有用。我怀疑它会在这里。
另请注意 ES6 箭头函数在多大程度上有助于清理此问题:
var populate = R.curry((coll, list) => R.map(
item => R.merge(item, R.prop(R.prop('key', item), coll)
), list));
您可以在 Ramda REPL
中看到所有这些
更新
我确实想看看这在无积分风格下会是什么样子。正如我所怀疑的那样,这远不如原始解决方案那么干净,远不如 ES6 版本,但也没有我担心的那么糟糕:
var populate = R.curry(R.useWith(
R.map,
R.flip(R.converge(
R.merge,
R.identity,
R.useWith(R.prop, R.prop('key'))
)),
R.identity
));
注意大量使用 Ramda 的两个古怪函数,useWith
and converge
。这些是功能组合的替代样式,通常非常有用。
你可以在 REPL.
中看到我如何将一个转换为另一个的步骤
我有两个项目:
列表:
[{
"key": "A",
...optionalAprops
}, {
"key": "C",
...optionalCProps
}]
Collection:
{
"A": {
...detailAprops
},
"B": {
...detailBprops
},
"C": {
...detailCprops
}
}
如何使用 Ramda.js 或函数式样式,使用 Collection 中的详细信息填充 List,已映射通过它的键? 结果应该像
[{
"key": "A",
...optionalAprops,
...detailAprops
}, {
"key": "C",
...optionalCprops,
...detailCprops
}]
我现在拥有的是
var populate = R.curry(function(coll, item) {
return R.merge(item, R.props(R.props('key', item), coll));
});
var result = R.map(populate(Collection))(List);
populate
函数在我看来非常 un-functional,因为它仍然传递状态。有没有更简洁的方法来完成相同的任务,使用 Ramda.js?
步骤细分为
- 迭代列表项
- 在项目中取
key
- 在 Collection 和
key
中查找详细信息 object
- 合并回项目
我认为将状态保持在您想要的位置的最简单方法是将 map
调用移动到您的函数中:
var populate = R.curry(function(coll, list) {
return R.map(function(item) {
return R.merge(item, R.prop(R.prop('key', item), coll))
}, list);
});
populate(Collection, List);
// or `populate(Collection)` to create a function that accepts a List
(请注意,我将 R.props
替换为 R.prop
。我认为这只是一个打字错误;否则您会包含各种可能不需要的键。)
可能有一些方法可以让这个免分,但它最终可能会变得更丑陋。也许不是;我没试过。但我认为无积分只有在它使代码更具可读性时才有用。我怀疑它会在这里。
另请注意 ES6 箭头函数在多大程度上有助于清理此问题:
var populate = R.curry((coll, list) => R.map(
item => R.merge(item, R.prop(R.prop('key', item), coll)
), list));
您可以在 Ramda REPL
中看到所有这些更新
我确实想看看这在无积分风格下会是什么样子。正如我所怀疑的那样,这远不如原始解决方案那么干净,远不如 ES6 版本,但也没有我担心的那么糟糕:
var populate = R.curry(R.useWith(
R.map,
R.flip(R.converge(
R.merge,
R.identity,
R.useWith(R.prop, R.prop('key'))
)),
R.identity
));
注意大量使用 Ramda 的两个古怪函数,useWith
and converge
。这些是功能组合的替代样式,通常非常有用。
你可以在 REPL.
中看到我如何将一个转换为另一个的步骤