merge by overwrite
The benefit of writing generic functions is immense. I'm using merge
which was written in another post and needs no modification to support your current need -
// main.js
import { merge } from './util'
const array1 = [[2], [], [3,5], [], [1]]
const array2 = [[], [], [4], [], [null]]
const result =
merge(array1, array2)
console.log(JSON.stringify(result))
// [[2],[],[4,5],[],[null]]
merge
is helpful because it intuitively handles nested objects and arrays (and even sparse arrays!) in any imaginable shape -
// util.js
const isObject = x =>
Object(x) === x
const mut = (o = {}, [ k, v ]) =>
(o[k] = v, o)
const merge = (left = {}, right = {}) =>
Object
.entries(right)
.map
( ([ k, v ]) =>
isObject(v) && isObject(left[k])
? [ k, merge(left[k], v) ]
: [ k, v ]
)
.reduce(mut, left)
export { merge }
Expand the snippet below to verify the results in your own browser -
// util.js
const isObject = x =>
Object (x) === x
const mut = (o = {}, [ k, v ]) =>
(o[k] = v, o)
const merge = (left = {}, right = {}) =>
Object
.entries(right)
.map
( ([ k, v ]) =>
isObject(v) && isObject(left[k])
? [ k, merge (left[k], v) ]
: [ k, v ]
)
.reduce(mut, left)
// export { merge }
// main.js
// impor { merge } from './util'
const array1 = [[2], [], [3,5], [], [1]]
const array2 = [[], [], [4], [], [null]]
const result =
merge(array1, array2)
console.log(JSON.stringify(result))
// [[2],[],[4,5],[],[null]]
immutable merge
Above our merge
function permanently alters one of the inputs arrays, array1
in this case. Here's a variation merge
that accepts any amount of objects/arrays and allows us to easily create a new array, without altering any of the inputs
const array1 = [[2], [], [3,5], [], [1]]
const array2 = [[], [], [4], [], [null]]
const result =
merge([], array1, array2)
console.log("result:", JSON.stringify(result)) // [[2],[],[4,5],[],[null]]
console.log("array1:", JSON.stringify(array1)) // [[2],[],[3,5],[],[1]]
console.log("array2:", JSON.stringify(array2)) // [[],[],[4],[],[null]]
Here's what the revised util
module could look like -
// util.js
const isArray =
Array.isArray
const isObject = x =>
Object(x) === x
const merge2 = (l = null, r = null) => // <- private; not exported
isArray(l) && isArray(r)
? merge([], l, r)
: isObject(l) && isObject(r)
? merge({}, l, r)
: r
const merge = (init = {}, ...all) => // <- public interface
all.reduce(replace, init)
const replace = (r = {}, o = {}) =>
{ for (const [ k, v ] of Object.entries(o))
r[k] = merge2(r[k], v)
return r
}
export { merge }
This was originally written for another question but it was never published. I'm glad I have a place to finally post it. Enjoy!
Expand the snippet below to verify the result in your browser -
//util.js
const isArray =
Array.isArray
const isObject = x =>
Object(x) === x
const merge2 = (l = null, r = null) =>
isArray(l) && isArray(r)
? merge([], l, r)
: isObject(l) && isObject(r)
? merge({}, l, r)
: r
const merge = (init = {}, ...all) =>
all.reduce(replace, init)
const replace = (r = {}, o = {}) =>
{ for (const [ k, v ] of Object.entries(o))
r[k] = merge2(r[k], v)
return r
}
// export { merge }
// main.js
// import { merge } from './util'
const array1 = [[2], [], [3,5], [], [1]]
const array2 = [[], [], [4], [], [null]]
const result =
merge([], array1, array2)
console.log("result:", JSON.stringify(result))
// [[2],[],[4,5],[],[null]]
console.log("array1:", JSON.stringify(array1))
// [[2],[],[3,5],[],[1]]
console.log("array2:", JSON.stringify(array2))
// [[],[],[4],[],[null]]