Reputation: 384
I have two arrays:
var a = [
{aId: 1, name: "a1"},
{aId: 2, name: "a2"}
];
var b = [
{parentId: 1, description: "b1"},
{parentId: 1, description: "b2"},
{parentId: 2, description: "b3"}
];
I want to merge these arrays based on the parentId === aId;
I did:
var c = _.map(a, function(obj) {
return _.assign(obj, _.find(b, {parentId: obj.aId}));
})
This works as expected, but I need it to handle duplicates - when this finds a match, it correctly merges it, but I instead need it to push the mergee into a new property, instead of merging.
What I get:
[
{aId: 1, name: "a1", description: "b1"},
{aId: 2, name: "a2", description: "b3"}
]
What I want:
[
{
aId: 1,
name: "a1",
b: [
{parentId: 1, description: "b1"},
{parentId: 1, description: "b2"}
]
},
{
aId: 2,
name: "a2",
b: [
{parentId: 2, description: "b1"}
]
}
]
The common property can of course be omitted;
Upvotes: 5
Views: 3877
Reputation: 19070
While this answer is very helpful and satisfies the original question to an extent, there's some discussion regarding mutation in the comments, which can cause unexpected behaviour, for example when using redux, or other libraries that rely on immutable state.
The original answer uses _.assign
which causes the mutation. The below uses the es6 spreads operator to return new objects into a new array.
const a = [{aId: 1, name: "a1"}, {aId: 2, name: "a2"}];
const b = [{parentId: 1, description: "b1"}, {parentId: 1, description: "b2"}, {parentId: 2, description: "b3"}];
const c = _.map(a, (obj) =>
({ ...obj, ...{ b: _.filter(b, {parentId: obj.aId}) }});
console.log('mimick original', c);
Your code is almost done; in the _.assign() you can pass an object with a property b
equal to the result of _.filter() instead of _.find():
{
b: _.filter(b, {parentId: obj.aId})
}
Note that _.find() returns the matched element, else undefined and _.filter() returns the new filtered array.
Code:
var a = [{aId: 1, name: "a1"}, {aId: 2, name: "a2"}],
b = [{parentId: 1, description: "b1"}, {parentId: 1, description: "b2"}, {parentId: 2, description: "b3"}];
_.map(a, function(obj) {
return _.assign(obj, {
b: _.filter(b, {parentId: obj.aId})
});
});
console.log(a);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
Upvotes: 3