Last active
August 24, 2019 06:34
-
-
Save lcherone/460bf9392b1c8bba57276ecf7e8cada9 to your computer and use it in GitHub Desktop.
Javascript recursive merge two arrays or objects where the first is the constraint. If item/value in B is not in A or is not the same type then A is used.
This file contains 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
/** | |
* Strict merge | |
* | |
* Recursive merge two arrays or objects where the first is the | |
* constraint, so if item/value in B is not in A or is not the | |
* same type as A then A is used. | |
* | |
* @param itemA An object or an array, which defines the merge | |
* @param itemB A matching object or array which will be merging in | |
* @returns object|array | |
*/ | |
const strictMerge = function (itemA, itemB) { | |
if (!itemB || typeof itemB !== typeof itemA) return itemA | |
if (Array.isArray(itemA) && Array.isArray(itemB)) { | |
return itemA.map((item, index) => { | |
if (itemB[index]) { | |
return Object.keys(item).reduce((acc, key) => { | |
acc[key] = typeof itemB[index][key] === 'object' && !Array.isArray(itemB[key]) ? | |
strictMerge(itemA[index][key], itemB[index][key]) : ( | |
typeof itemB[index][key] !== 'undefined' ? ( | |
typeof itemB[index][key] !== typeof itemA[index][key] ? itemA[index][key] : itemB[index][key] | |
) : itemA[index][key] | |
) | |
return acc | |
}, {}) | |
} | |
return item | |
}, []) | |
} else { | |
return Object.keys(itemA).reduce((acc, key) => { | |
acc[key] = typeof itemB[key] === 'object' && !Array.isArray(itemB[key]) ? | |
strictMerge(itemA[key], itemB[key]) : ( | |
typeof itemB[key] !== 'undefined' ? ( | |
typeof itemB[key] !== typeof itemA[key] ? itemA[key] : itemB[key] | |
) : itemA[key] | |
) | |
return acc | |
}, {}) | |
} | |
} | |
// example, copy testIn but constraint to A | |
let testIn = { | |
a: { | |
a1: false, | |
a2: 100, | |
a3: { | |
b1: ['bar'], | |
b3: true | |
}, | |
a4: { | |
b1: true, | |
b3: false, | |
b4: { | |
c1: 'this should be true (type check), a.a2 = 100 and a.a3.b3 should be set true' | |
} | |
} | |
} | |
} | |
// passed in as an array (to cover test, not required) | |
let result = strictMerge([{ | |
a: { | |
a1: true, | |
a2: -1, | |
a3: { | |
b1: [], | |
b3: false | |
}, | |
a4: { | |
b1: true, | |
b3: false, | |
b4: { | |
c1: true | |
} | |
} | |
} | |
}], [testIn]) | |
console.log(JSON.stringify(result, null, 2)) | |
` | |
[ | |
{ | |
"a": { | |
"a1": false, | |
"a2": 100, | |
"a3": { | |
"b1": [ | |
"bar" | |
], | |
"b3": true | |
}, | |
"a4": { | |
"b1": true, | |
"b3": false, | |
"b4": { | |
"c1": true | |
} | |
} | |
} | |
} | |
] | |
` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment