Last active
August 29, 2016 21:27
-
-
Save raphaelchaib/d949a04e154d154752af16a57c704bc1 to your computer and use it in GitHub Desktop.
Javascript: Merge two multidimensional objects, respecting it's type
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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