Reputation: 1449
In my code, I have used two forEach loops. But in order to optimize my code, I have been instructed not to use forEach loop inside a forEach loop. So I don't want to loop over the second array obj3. I just want to get the values at a certain position without using the inner forEach loop. Here is my code : -
var obj2 = [{
"name": "4134",
"calls": [
]
}]
var obj3 = [{ Channel: 'SIP/4134-0004462a',
State: 'Up',
Accountcode: '7013658596'},
{ Channel: 'SIP/4334-sa',
State: 'Up',
Accountcode: '07717754702',
}]
var function = (obj2, obj3) => {
obj2.forEach((a) =>
obj3.forEach((b) => {
if (b.Channel.includes(a.name)) a.calls = (a.calls || []).concat(Object.assign({}, { MobileNo: b.Accountcode, Status : b.State}));
})
);
};
function(obj2, obj3);
The above code loops through obj2 and obj3 and if the value of the name key exist in the Channel key's value then it picks the Accountcode and State from obj3 and pushes them in the calls array of the obj2. Here is the output array:-
[ {
"name": "4134",
"calls": [
{
"MobileNo": "7013658596",
"Status": "Up"
}
]
}]
What I have done so far
var func = (obj2, obj3) => {
var channelArr = [];
const Channels = obj3.reduce((acc, curVal) => {
obj2.forEach((item)=>{
if(curVal.Channel.includes(item.name)){
item.calls.push({'MobileNo':curVal.Accountcode,'Status': curVal.State})
}
})
return obj2;
}, [])
};
I tried doing it using reduce function but I'm really not sure if this can improve the performance. Please do let me know if you have better suggestions.
Upvotes: 3
Views: 1100
Reputation: 2941
Hope this helps. I have created lookup table like structure with help of obj3. and after that when traversing obj2 just checking whether name is present in lookup table or not and if present then assign some object to calls
var obj2=[{name:"4134",calls:[]}],obj3=[{Channel:"SIP/4134-0004462a",State:"Up",Accountcode:"7013658596"},{Channel:"SIP/4334-sa",State:"Up",Accountcode:"07717754702"}];
var fun = (obj2, obj3) => {
//creating temp object which conatin name as key and index as value from obj2
var temp={};
obj3.forEach((b,i)=>{
var myRegexp = /\/(\d+)/g;
var name=myRegexp.exec(b.Channel);
temp[name[1]]=i;
});
obj2.forEach(a => {
if(temp[a.name] !== undefined) { //if temp object contain key then we need to merge this object
var b = obj3[temp[a.name]];
a.calls = (a.calls || []).concat(Object.assign({}, {
MobileNo: b.Accountcode,
Status : b.State
}));
}
});
console.log(obj2);
}
fun(obj2,obj3);
Upvotes: 1
Reputation: 1745
I tried using filter
and map
, check it out if this works for you.
const result = obj2.map(a => {
const foundAll = obj3.filter(
({ Channel, Accountcode, State }) =>
Channel.includes(a.name) && { Accountcode, State }
);
return {
name: a.name,
calls: [...a.calls, foundAll]
};
});
console.info(result);
Find working Bin here.
Upvotes: 1
Reputation: 370689
Since the name
s are in a predictable location inside Channel
, you can build an object indexed by name
s from the obj3
initially, and then just use bracket notation to get the array you need, O(n)
:
var obj2 = [{
"name": "4134",
"calls": [
]
}];
var obj3 = [{
Channel: 'SIP/4134-0004462a',
State: 'Up',
Accountcode: '7013658596'
},
{
Channel: 'SIP/4334-sa',
State: 'Up',
Accountcode: '07717754702',
}
]
const objsByName = obj3.reduce((a, item) => {
const { Channel } = item;
const name = Channel.match(/\/(\d+)/)[1];
if (!a[name]) a[name] = [];
a[name].push(item);
return a;
}, {});
obj2.forEach(({ name, calls }) => {
calls.push(...objsByName[name]);
});
console.log(obj2);
Upvotes: 2