Skip to content

Instantly share code, notes, and snippets.

@raphaelchaib
Last active August 29, 2016 21:27
Show Gist options
  • Save raphaelchaib/d949a04e154d154752af16a57c704bc1 to your computer and use it in GitHub Desktop.
Save raphaelchaib/d949a04e154d154752af16a57c704bc1 to your computer and use it in GitHub Desktop.
Javascript: Merge two multidimensional objects, respecting it's type
function merge(A, B, depth) {
if ( typeof target !== 'object' ) {
target = {};
}
for (var property in source) {
if ( source.hasOwnProperty(property) ) {
var sourceProperty = source[ property ];
if ( typeof sourceProperty === 'object' ) {
target[ property ] = merge( target[ property ], sourceProperty );
continue;
}
target[ property ] = sourceProperty;
}
}
for (var a = 2, l = arguments.length; a < l; a++) {
merge(target, arguments[a]);
}
return target;
}
function merge(target, source) {
console.info('merge::target::PRE', target);
console.info('merge::source::PRE', JSON.stringify(source));
var item, tItem, o, idx;
// If either argument is undefined, return the other.
// If both are undefined, return undefined.
if (typeof source == 'undefined') {
return source;
} else if (typeof target == 'undefined') {
return target;
}
// Assume both are objects and don't care about inherited properties
for (var prop in source) {
item = source[prop];
if (typeof item == 'object' && item !== null) {
if (isArray(item) && item.length) {
// deal with arrays, will be either array of primitives or array of objects
// If primitives
if (typeof item[0] != 'object') {
// if target doesn't have a similar property, just reference it
tItem = target[prop];
if (!tItem) {
target[prop] = item;
// Otherwise, copy only those members that don't exist on target
} else {
// Create an index of items on target
o = {};
for (var i=0, iLen=tItem.length; i<iLen; i++) {
o[tItem[i]] = true
}
// Do check, push missing
for (var j=0, jLen=item.length; j<jLen; j++) {
if ( !(item[j] in o) ) {
tItem.push(item[j]);
}
}
}
} else {
// Deal with array of objects
// Create index of objects in target object using ID property
// Assume if target has same named property then it will be similar array
idx = {};
tItem = target[prop] || [];
if(!!tItem && tItem.length) {
for (var k=0, kLen=tItem.length; k<kLen; k++) {
idx[tItem[k].id] = tItem[k];
}
}
// Do updates
for (var l=0, ll=item.length; l<ll; l++) {
// If target doesn't have an equivalent, just add it
if (!(item[l].id in idx)) {
tItem.push(item[l]);
} else {
merge(idx[item[l].id], item[l]);
}
}
console.warn('tItem2',tItem);
console.log('prop', prop);
target[prop] = tItem;
}
} else {
// deal with object
merge(target[prop],item);
}
} else {
// item is a primitive, just copy it over
target[prop] = item;
}
}
console.info('merge::target::POST', target);
return target;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment