Skip to content

Instantly share code, notes, and snippets.

@lcherone
Last active August 24, 2019 06:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lcherone/460bf9392b1c8bba57276ecf7e8cada9 to your computer and use it in GitHub Desktop.
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.
/**
* 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