Reputation: 87
I have Two JSON Array Like:
var a = [{_id:1, name: "Bhavin"},{_id:2, name: "Raj"},{_id:3, name: "Rahul"}];
var b = [{_id:1, post: "Developer"},{_id:2, post: "Quality Analyst"}];
Now, I want merged Like:
var c = [{_id:1, name: "Bhavin", post: "Developer"},{_id:2, name: "Raj", post: "Quality Analyst"},{_id:3, name: "Rahul"}];
I know I can do it easily in plain JavaScript by the use of two for loop... But that takes n*n
time.
I want to solve this problem in only n
time.
How can I achieve that?
Upvotes: 0
Views: 3144
Reputation: 30098
You can easily solve this by mapping the lesser sized array into a key-value composed object, where the keys of the object are the ids and their values are the associated values themselves. Once the association is accomplished, we can iterate and transform the greater sized array by assigning the missing values from the mapped object.
// ensure that b has more items than a
// to prevent data loss
if(a.length > b.length) {
var t = b;
b = a;
a = t;
}
// create an object composed of of ids as key associated with each object.
// a loash alternative is:
// var map = _.keys(a, '_id');
var map = a.reduce((r, v) => (r[v._id] = v, r), {});
// assign missing properties from each object from the associated mapped object.
var result = b.map(v => ({...map[v._id], ...v}));
var a = [{_id:1, name: "Bhavin"},{_id:2, name: "Raj"},{_id:3, name: "Rahul"}];
var b = [{_id:1, post: "Developer"},{_id:2, post: "Quality Analyst"}];
// ensure that b has more items than a
// to prevent data loss
if(a.length > b.length) {
var t = b;
b = a;
a = t;
}
// create an object composed of of ids as key associated with each object.
// a loash alternative is:
// var map = _.keys(a, '_id');
var map = a.reduce((r, v) => (r[v._id] = v, r), {});
// assign missing properties from each object from the associated mapped object.
var result = b.map(v => ({...map[v._id], ...v}));
console.log(result);
.as-console-wrapper{min-height:100%;top:0}
Upvotes: 1
Reputation: 834
Hi there you can achieve it using below code
_.map(a, function (el){
return _.merge(el , _.find(b, {_id: el._id }))
})
// using chain, i would prefer first it looks clean :-p
_.chain(a).map(function (o){
return _.merge(o, _.find(b, {_id: o._id }))
})
.value()
I will try it with chain and update the answer
Upvotes: 0
Reputation: 1513
You should use lodash mergeWith
function.
var a = [{_id:1, name: "Bhavin"},{_id:2, name: "Raj"},{_id:3, name: "Rahul"}];
var b = [{_id:1, post: "Developer"},{_id:2, post: "Quality Analyst"}];
// ouput [{_id:1, name: "Bhavin", post: "Developer"},{_id:2, name: "Raj", post: "Quality Analyst"},{_id:3, name: "Rahul"}];
function customizer(firstValue, secondValue) {
return Object.assign({}, firstValue, secondValue);
}
console.log(_.mergeWith(a, b, customizer));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.js"></script>
Upvotes: 2
Reputation: 370879
It's quite possible to achieve this in plain Javascript in O(n)
time:
var a = [{_id:1, name: "Bhavin"},{_id:2, name: "Raj"},{_id:3, name: "Rahul"}];
var b = [{_id:1, post: "Developer"},{_id:2, post: "Quality Analyst"}];
const aById = a.reduce((map, { _id, name }) => map.set(_id, name), new Map());
const bById = b.reduce((map, { _id, post }) => map.set(_id, post), new Map());
const combined = [...aById.entries()].map(([_id, name]) => {
const person = { _id, name };
const post = bById.get(_id);
if (post) person.post = post;
return person;
});
console.log(combined);
var c = [{_id:1, name: "Bhavin", post: "Developer"},{_id:2, name: "Raj", post: "Quality Analyst"},{_id:3, name: "Rahul"}];
Map
s are guaranteed to have O(1)
lookup time. Object hashmaps (like {'1': 'Developer', '2': 'Quality Analyst'}
) are not.
You had a couple of typos in your original code, I'm assuming those were unintentional - I fixed them in the snippet above.
Upvotes: 0