使用镜头合并两个对象的最简单方法
Simplest method to merge two objects using a Lens
我是 Ramda 的新手,我试图限制自己在调整时不使用 vanilla JS 方法来完成这样的任务。我被困在一些感觉很简单的事情上。当我需要像这样将一些东西链接在一起时,Ramda 对我来说就失去了清晰度。
我使用 R.groupBy
将一些其他数据聚合到一个带有一些键的对象中,我有一个目标对象,我想将其合并 - 但是来自 groupby 的键嵌套在其中。
我可以在目标 属性 上创建一个带有镜头的 view 来查看转换后的数据以匹配 - 我不太确定如何反向操作以将分组数据应用于嵌套对象。
let ungroupedData = [
{"tag":"foo","id":99}, {"tag":"bar","id":33}, {"tag":"foo","id":14}, {"tag":"bar","id":26},
{"tag":"baz","id":99}, {"tag":"qux","id":33}, {"tag":"foo","id":49}, {"tag":"bar","id":13}
];
let groupedData = R.map(R.pluck('id'), R.groupBy(R.prop('tag'),ungroupedData));
console.log({groupedData});
// groupedData:
// {
// "foo": [99, 14, 49],
// "bar": [33, 26, 13],
// "baz": [99],
// "qux": [33]
// }
let nestedTargetObjectToMerge = {
"foo": {
//...
"ids": [344, 121],
//...
},
"bar": {
//...
"ids": [103, 66],
//...
}
}
// a view of the target object using a lens which matches groupedData
let view = R.map(R.view(R.lensProp("ids")), nestedTargetObjectToMerge);
console.log({view});
// view:
// {
// "foo": [344, 121],
// "bar": [103, 66]
// }
/*
let merged = ??
// R.mergeDeepWithKey ?
// R.over?
*/
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
预期结果
{
"foo" : {
"ids" : [344, 121, 99, 14, 49],
},
"bar" : {
"ids" : [103, 66, 33, 26, 13],
},
"baz" : {
"ids": [99],
},
"qux" : {
"ids" : [33],
}
}
分组后,映射组,并使用 R.applySpec
和 R.pluck
创建对象 ids
。现在你可以使用 R.mergeDeepWith
和 R.concat
结合两个对象上的 ids
:
const { pipe, groupBy, prop, map, applySpec, pluck, mergeDeepWith, concat } = R;
const groupData = pipe(
groupBy(prop('tag')),
map(applySpec({
ids: pluck('id')
}))
)
const ungroupedData = [{"tag":"foo","id":99},{"tag":"bar","id":33},{"tag":"foo","id":14},{"tag":"bar","id":26},{"tag":"baz","id":99},{"tag":"qux","id":33},{"tag":"foo","id":49},{"tag":"bar","id":13}];
const nestedTargetObjectToMerge = {"foo":{"ids":[344,121]},"bar":{"ids":[103,66]}};
const groupedData = groupData(ungroupedData);
const result = mergeDeepWith(
concat,
nestedTargetObjectToMerge,
groupedData
);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
我的回答与 Ori Drori 的相似,但差异很大,因此也包括在内:
const extractIds = compose (map (objOf ('ids')), map (pluck ('id')), groupBy (prop ('tag')))
const group = compose (flip (mergeDeepWith (concat)), extractIds)
const nestedTargetObjectToMerge = {foo: {ids: [344, 121]}, bar: {ids: [103, 66]}}
const ungroupedData = [{tag: "foo", id: 99}, {tag: "bar", id: 33}, {tag: "foo", id: 14}, {tag: "bar", id: 26}, {tag: "baz", id: 99}, {tag: "qux", id: 33}, {tag: "foo", id: 49}, {tag: "bar", id: 13}]
console .log (
group (ungroupedData) (nestedTargetObjectToMerge)
)
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.28.0/ramda.min.js"></script>
<script> const {compose, map, objOf, pluck, groupBy, prop, flip, mergeDeepWith, concat} = R </script>
此处 extractIds
将未分组的数据转换为与目标对象相同的格式,然后 group
使用它将其传递到 mergeDeepWith (concat)
。 extreactId
可以很容易地内嵌到 group
中,但我发现这样更易读。
不过,我想评论一下:
I'm new to Ramda and trying to restrict myself to not resorting to vanilla JS methods for tasks like this while I adjust. I'm stuck on something that feels very simple. Ramda loses clarity for me as soon as I need to chain some things together like this.
我是 Ramda 的创始人和首席维护者之一。我是一个忠实粉丝。但我会非常警惕这种哲学。 Ramda 是一个工具;它旨在使以某种风格工作更容易。但它不应该为你接管一切。它通常可用于使您的代码更清晰。当它发生时使用它。如果没有,不要试图挤进去。如果这只是一个学习练习,那么当然可以使用 Ramda 解决方案。但为了你真正的工作,不要试图强迫它。
而且,虽然我对上面的解决方案以及 Ori Drori 的版本非常满意,但我不会打折使用单折叠的普通 JS 解决方案,如下所示:
const group = (xs) => (target) =>
xs .reduce ((a, {tag, id}) => ({
...a,
[tag]: {...(a [tag] ?? {}), ids: [... (a [tag] ?.ids ?? []), id]}
}), target)
const nestedTargetObjectToMerge = {foo: {ids: [344, 121]}, bar: {ids: [103, 66]}}
const ungroupedData = [{tag: "foo", id: 99}, {tag: "bar", id: 33}, {tag: "foo", id: 14}, {tag: "bar", id: 26}, {tag: "baz", id: 99}, {tag: "qux", id: 33}, {tag: "foo", id: 49}, {tag: "bar", id: 13}]
console .log (
group (ungroupedData) (nestedTargetObjectToMerge)
)
.as-console-wrapper {max-height: 100% !important; top: 0}
我是 Ramda 的新手,我试图限制自己在调整时不使用 vanilla JS 方法来完成这样的任务。我被困在一些感觉很简单的事情上。当我需要像这样将一些东西链接在一起时,Ramda 对我来说就失去了清晰度。
我使用 R.groupBy
将一些其他数据聚合到一个带有一些键的对象中,我有一个目标对象,我想将其合并 - 但是来自 groupby 的键嵌套在其中。
我可以在目标 属性 上创建一个带有镜头的 view 来查看转换后的数据以匹配 - 我不太确定如何反向操作以将分组数据应用于嵌套对象。
let ungroupedData = [
{"tag":"foo","id":99}, {"tag":"bar","id":33}, {"tag":"foo","id":14}, {"tag":"bar","id":26},
{"tag":"baz","id":99}, {"tag":"qux","id":33}, {"tag":"foo","id":49}, {"tag":"bar","id":13}
];
let groupedData = R.map(R.pluck('id'), R.groupBy(R.prop('tag'),ungroupedData));
console.log({groupedData});
// groupedData:
// {
// "foo": [99, 14, 49],
// "bar": [33, 26, 13],
// "baz": [99],
// "qux": [33]
// }
let nestedTargetObjectToMerge = {
"foo": {
//...
"ids": [344, 121],
//...
},
"bar": {
//...
"ids": [103, 66],
//...
}
}
// a view of the target object using a lens which matches groupedData
let view = R.map(R.view(R.lensProp("ids")), nestedTargetObjectToMerge);
console.log({view});
// view:
// {
// "foo": [344, 121],
// "bar": [103, 66]
// }
/*
let merged = ??
// R.mergeDeepWithKey ?
// R.over?
*/
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
预期结果
{
"foo" : {
"ids" : [344, 121, 99, 14, 49],
},
"bar" : {
"ids" : [103, 66, 33, 26, 13],
},
"baz" : {
"ids": [99],
},
"qux" : {
"ids" : [33],
}
}
分组后,映射组,并使用 R.applySpec
和 R.pluck
创建对象 ids
。现在你可以使用 R.mergeDeepWith
和 R.concat
结合两个对象上的 ids
:
const { pipe, groupBy, prop, map, applySpec, pluck, mergeDeepWith, concat } = R;
const groupData = pipe(
groupBy(prop('tag')),
map(applySpec({
ids: pluck('id')
}))
)
const ungroupedData = [{"tag":"foo","id":99},{"tag":"bar","id":33},{"tag":"foo","id":14},{"tag":"bar","id":26},{"tag":"baz","id":99},{"tag":"qux","id":33},{"tag":"foo","id":49},{"tag":"bar","id":13}];
const nestedTargetObjectToMerge = {"foo":{"ids":[344,121]},"bar":{"ids":[103,66]}};
const groupedData = groupData(ungroupedData);
const result = mergeDeepWith(
concat,
nestedTargetObjectToMerge,
groupedData
);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
我的回答与 Ori Drori 的相似,但差异很大,因此也包括在内:
const extractIds = compose (map (objOf ('ids')), map (pluck ('id')), groupBy (prop ('tag')))
const group = compose (flip (mergeDeepWith (concat)), extractIds)
const nestedTargetObjectToMerge = {foo: {ids: [344, 121]}, bar: {ids: [103, 66]}}
const ungroupedData = [{tag: "foo", id: 99}, {tag: "bar", id: 33}, {tag: "foo", id: 14}, {tag: "bar", id: 26}, {tag: "baz", id: 99}, {tag: "qux", id: 33}, {tag: "foo", id: 49}, {tag: "bar", id: 13}]
console .log (
group (ungroupedData) (nestedTargetObjectToMerge)
)
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.28.0/ramda.min.js"></script>
<script> const {compose, map, objOf, pluck, groupBy, prop, flip, mergeDeepWith, concat} = R </script>
此处 extractIds
将未分组的数据转换为与目标对象相同的格式,然后 group
使用它将其传递到 mergeDeepWith (concat)
。 extreactId
可以很容易地内嵌到 group
中,但我发现这样更易读。
不过,我想评论一下:
I'm new to Ramda and trying to restrict myself to not resorting to vanilla JS methods for tasks like this while I adjust. I'm stuck on something that feels very simple. Ramda loses clarity for me as soon as I need to chain some things together like this.
我是 Ramda 的创始人和首席维护者之一。我是一个忠实粉丝。但我会非常警惕这种哲学。 Ramda 是一个工具;它旨在使以某种风格工作更容易。但它不应该为你接管一切。它通常可用于使您的代码更清晰。当它发生时使用它。如果没有,不要试图挤进去。如果这只是一个学习练习,那么当然可以使用 Ramda 解决方案。但为了你真正的工作,不要试图强迫它。
而且,虽然我对上面的解决方案以及 Ori Drori 的版本非常满意,但我不会打折使用单折叠的普通 JS 解决方案,如下所示:
const group = (xs) => (target) =>
xs .reduce ((a, {tag, id}) => ({
...a,
[tag]: {...(a [tag] ?? {}), ids: [... (a [tag] ?.ids ?? []), id]}
}), target)
const nestedTargetObjectToMerge = {foo: {ids: [344, 121]}, bar: {ids: [103, 66]}}
const ungroupedData = [{tag: "foo", id: 99}, {tag: "bar", id: 33}, {tag: "foo", id: 14}, {tag: "bar", id: 26}, {tag: "baz", id: 99}, {tag: "qux", id: 33}, {tag: "foo", id: 49}, {tag: "bar", id: 13}]
console .log (
group (ungroupedData) (nestedTargetObjectToMerge)
)
.as-console-wrapper {max-height: 100% !important; top: 0}