recursive differential
After almost 3 years, I will gladly provide an updated answer to this question.
We will start with two different objects.
const x =
{ a: 1, b: 2, c: 3 }
const y =
{ a: 1, b: 3, d: 4 }
console.log (diff (x, y))
a. b . x c, y d. ????
diff, a b . , , diff left right
console.log (diff (x, y))
- -
b, c d - -
left / right - "" - ,
b 2, b 3; c 3, c undefined
, ,
const x =
{ a: { b: { c: 1, d: 2, e: 3 } } }
const y =
{ a: { b: { c: 1, d: 3, f: 4 } } }
console.log (diff (x, y))
, diff , . , , , diff ""
const x1 =
{ a: 1, b: { c: { d: 2 } } }
const x2 =
{ a: 1, b: { c: { d: 2 } } }
console.log (diff (x1, x2))
diff, . "" , "" , , . ,
const diff = (x = {}, y = {}) =>
merge
( diff1 (x, y, "left")
, diff1 (y, x, "right")
)
diff1
"" , diff1, "" , , "" , merge
, . diff1 , merge . diff1
const empty =
{}
const isObject = x =>
Object (x) === x
const diff1 = (left = {}, right = {}, rel = "left") =>
Object.entries (left)
.map
( ([ k, v ]) =>
isObject (v) && isObject (right[k])
? [ k, diff1 (v, right[k], rel) ]
: right[k] !== v
? [ k, { [rel]: v } ]
: [ k, empty ]
)
.reduce
( (acc, [ k, v ]) =>
v === empty
? acc
: { ...acc, [k]: v }
, empty
)
diff1 , rel. "left", "" . , diff1 . diff1 .
const x =
{ a: 1, b: 2, c: 3 }
const y =
{ a: 1, b: 3, d: 4 }
console.log (diff1 (x, y, "left"))
console.log (diff1 (y, x, "right"))
, "left" "right" . , , , diff...
const customDiff = (original = {}, modified = {}) =>
merge
( diff1 (x, y, "original")
, diff1 (y, x, "modified")
)
customDiff
( { host: "localhost", port: 80 }
, { host: "127.0.0.1", port: 80 }
)
// { host: { original: 'localhost', modified: '127.0.0.1' } }
, original modified , left right.
, , . merge .
const x =
{ a: 1, b: 1, c: 1 }
const y =
{ b: 2, d: 2 }
console.log (merge (x, y))
, , merge .
const x =
{ a: { b: { c: 1, d: 1 } } }
const y =
{ a: { b: { c: 2, e: 2 } }, f: 2 }
console.log (merge (x, y))
merge
const merge = (left = {}, right = {}) =>
Object.entries (right)
.reduce
( (acc, [ k, v ]) =>
isObject (v) && isObject (left [k])
? { ...acc, [k]: merge (left [k], v) }
: { ...acc, [k]: v }
, left
)
! ,
const empty =
{}
const isObject = x =>
Object (x) === x
const diff1 = (left = {}, right = {}, rel = "left") =>
Object.entries (left)
.map
( ([ k, v ]) =>
isObject (v) && isObject (right[k])
? [ k, diff1 (v, right[k], rel) ]
: right[k] !== v
? [ k, { [rel]: v } ]
: [ k, empty ]
)
.reduce
( (acc, [ k, v ]) =>
v === empty
? acc
: { ...acc, [k]: v }
, empty
)
const merge = (left = {}, right = {}) =>
Object.entries (right)
.reduce
( (acc, [ k, v ]) =>
isObject (v) && isObject (left [k])
? { ...acc, [k]: merge (left [k], v) }
: { ...acc, [k]: v }
, left
)
const diff = (x = {}, y = {}) =>
merge
( diff1 (x, y, "left")
, diff1 (y, x, "right")
)
const x =
{ a: { b: { c: 1, d: 2, e: 3 } } }
const y =
{ a: { b: { c: 1, d: 3, f: 4 } } }
console.log (diff (x, y))
console.log (diff (diff (x,y), diff (x,y)))
Hide result
diff, . merge, diff, , . , . , diff, , merge .
:
diff , , , ? , , .
. . , diff
const diff = (x = {}, y = {}) =>
merge
( diff1 (x, y, "left")
, diff1 (y, x, "right")
)
merge, mut, [ key, value ] , o. , , , mut
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)
const x =
[ 1, 2, 3, 4, 5 ]
const y =
[ 0, 0, 0 ]
const z =
[ , , , , , 6 ]
console.log (merge (x, y))
console.log (merge (y, z))
console.log (merge (x, z))
const x =
{ a: [ { b: 1 }, { c: 1 } ] }
const y =
{ a: [ { d: 2 }, { c: 2 }, { e: 2 } ] }
console.log (merge (x, y))
diff1
const diff1 = (left = {}, right = {}, rel = "left") =>
Object.entries (left)
.map
( ([ k, v ]) =>
isObject (v) && isObject (right[k])
? [ k, diff1 (v, right[k], rel) ]
: right[k] !== v
? [ k, { [rel]: v } ]
: [ k, {} ]
)
.filter
( ([ k, v ]) =>
Object.keys (v) .length !== 0
)
.reduce
( mut
, isArray (left) && isArray (right) ? [] : {}
)
, - , !
const x =
{ a: 1, b: [ { c: 1 }, { d: 1 }, { e: 1 } ] }
const y =
{ a: 1, b: [ { c: 2 }, { d: 1 }, 5, 6 ], z: 2 }
console.log (diff (x, y))
diff1 ,
const x =
[ 1, 2, 3, 4 ]
const y =
[ 1, 2, 9 ]
const z =
[ 1, 2, 9 ]
console.log (diff (x, y))
console.log (diff (y, z))
const isObject = x =>
Object (x) === x
const isArray =
Array.isArray
const mut = (o, [ k, v ]) =>
(o [k] = v, o)
const diff1 = (left = {}, right = {}, rel = "left") =>
Object.entries (left)
.map
( ([ k, v ]) =>
isObject (v) && isObject (right[k])
? [ k, diff1 (v, right[k], rel) ]
: right[k] !== v
? [ k, { [rel]: v } ]
: [ k, {} ]
)
.filter
( ([ k, v ]) =>
Object.keys (v) .length !== 0
)
.reduce
( mut
, isArray (left) && isArray (right) ? [] : {}
)
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)
const diff = (x = {}, y = {}) =>
merge
( diff1 (x, y, "left")
, diff1 (y, x, "right")
)
const x =
{ a: 1, b: [ { c: 1 }, { d: 1 }, { e: 1 } ] }
const y =
{ a: 1, b: [ { c: 2 }, { d: 1 }, 5, 6 ], z: 2 }
console.log (diff (x, y))
Hide result
diff , .
Q & A intersect diff.