I'm trying to create a single object which takes information from two separate objects (taken from ajax calls). Basically we have a list of tags, and also a list of elements, these items are related, however the tag object doesn't contain all of the information I need to populate all the data.
For example:
List of tags:
[
{"id": 1, "name": "yadda", "description": "yadda yadda"},
{"id": 2, "name": "yadda1", "description": "yadda yadda1"},
{"id": 7, "name": "yadda2", "description": "yadda yadda2"},
{"id": 10, "name": "yadda3", "description": "yadda yadda3"}
]
List of Elements (more info):
[
{"id": 1, "icon": "icon1.gif"},
{"id": 2, "icon": "icon2.gif"},
{"id": 7, "icon": "icon3.gif"},
{"id": 10, "icon": "icon4.gif"}
]
I need to compare the two objects by the ID, and combine them into a new object that gives me access to all of the data in both of those objects.
If it helps, this is an angular project, and I am already using Underscore, I believe there must be some way to do this with underscore, but i'm not very familliar with it.
Quick and dirty:
var a = [
{"id": 1, "name": "yadda", "description": "yadda yadda"},
{"id": 2, "name": "yadda1", "description": "yadda yadda1"},
{"id": 7, "name": "yadda2", "description": "yadda yadda2"},
{"id": 10, "name": "yadda3", "description": "yadda yadda3"}
],
b = [
{"id": 1, "icon": "icon1.gif"},
{"id": 2, "icon": "icon2.gif"},
{"id": 7, "icon": "icon3.gif"},
{"id": 10, "icon": "icon4.gif"}
];
var result = a.map(function(v){
var ret;
$.each(b, function(k, v2){
if(v2.id === v.id){
ret = $.extend({}, v2, v); // merge the objects in to a new one
return false; // break the loop
}
});
return ret;
});
console.log(result);
http://jsfiddle.net/YwUA2/
As you can see, this assumes that there's a 1:1 relationship between the objects in the two arrays.
http://plnkr.co/edit/77kMDeqkGvyVK87FISGl?p=info
function combine(x,y){
var z = x;
for (i=0; i<x.length; i++){
for (j=0; j<y.length; j++){
if (x[i].id === y[j].id) {
z[i].icon = y[j].icon;
break;
}
}
}
return z;
}
Seems like migration from SQL JOIN to Javascript code.
Here's a LEFT JOIN implement:
var hash2 = _.object(
_.map(list2,function(row){
return [row.id,_.omit(row,"id")];
})
);
var newList = _.map(list1,function(row){
return _.extend(row,hash2[row.id]||{});
});
For whats its worth, no libraries, just vanilla js
Function that does the work:
function mergeObjArrays(list1, list2) {
var mergedList = [],
i = 0,
j = 0,
k = 0,
l1 = list1.length,
l2 = list2.length,
listMatchFound = false,
mergedObj,
mergeMatchFound = false;
for (i = 0; i < l1; i++) {
for (j = 0; j < l2; j++) {
if (list1[i].id === list2[j].id) {
listMatchFound = true;
mergedObj = mergeObj(list1[i], list2[j]);
for (k = 0; k < mergedList.length; k++) {
if (mergedList[k].id === mergedObj.id) {
mergedObj = mergeObj(mergedList[k], mergedObj);
mergedList[k] = mergedObj;
mergeMatchFound = true;
break;
}
}
if (!mergeMatchFound) {
mergedList.push(mergedObj);
} else {
mergeMatchFound = false; //reset ready for another iteration
}
}
}
if (!listMatchFound) {
mergedList.push(list1[i]);
} else {
listMatchFound = false; //reset ready for another iteration
}
}
return mergedList;
function mergeObj(obj1, obj2) {
for (var o in obj1) {
obj2[o] = obj1[o];
}
return obj2;
}
}
Example usage
var a = [
{"id": 1, "name": "yadda", "description": "yadda yadda"},
{"id": 2, "name": "yadda1", "description": "yadda yadda1"},
{"id": 7, "name": "yadda2", "description": "yadda yadda2"},
{"id": 10, "name": "yadda3", "description": "yadda yadda3"}
];
var b = [
{"id": 7, "icon": "icon3.gif"},
{"id": 10, "icon": "icon4.gif"},
{"id": 2, "icon": "icon2.gif"},
{"id": 2, "title": "Number 2 title"},
{"id": 1, "icon": "icon1.gif"}
];
//used like
var result = mergeObjArrays(a,b);
console.log(result)
//outputs (although not necessarily in order)
[
{"id": 1, "name": "yadda", "description": "yadda yadda","icon": "icon1.gif"},
{"id": 2, "name": "yadda1", "description": "yadda yadda1","icon": "icon2.gif","title": "Number 2 title"},
{"id": 7, "name": "yadda2", "description": "yadda yadda2","icon": "icon3.gif"},
{"id": 10, "name": "yadda3", "description": "yadda yadda3","icon": "icon4.gif"}
]
This will ineffect do a merge based on objects in set1 (a in this example), (i.e. include object if occurs in set1, or merge object if in both set1 and set2 but not if it occurs only in set2), and deal with a 1 to many relationship as well (i.e. multiple instances of an object in set2 will be merged into one object with set1's obj) and order of the objects doesn't matter. You could even go a step further and pass in the field that is the key (common element) in both objects, in this example "id" is hardwired to the mergeObjArrays function.