this will treat [1,2,3]
and [3,2,1]
as equal (deep object)
since I needed to visualize the difference between:
[
{
"a":1,
"b":1
},
{
"a":1,
"b":1
}
]
and
[
{
"a":1,
"b":1
},
{
"a":"OH NO",
"b":"an insertion"
},
{
"a":1,
"b":1
}
]
so I wanted to see them collide, here's what's left:
[]
and
[
{
"a":"OH NO",
"b":"an insertion"
}
]
imo this is the best way to represent it.
{add:{...},upd:{...},del:{...}}
is hard to read
I provide 2 functions : ObjectCollide(obj1,obj2)
and ArrayCollide(arr1,arr2)
console.log(ArrayCollide([1,2,3],[3,2,1]))
// false
//everything collided -> false
console.log(ArrayCollide([1],[2,1]))
// [ [], [ 2 ] ]
//1 and 1 collided, even if they are on different indices
//array of objects
const arr1 =
[
{
"a":1,
"b":1
},
{
"a":1,
"b":1
}
]
const arr2 =
[
{
"a":1,
"b":1
},
{
"a":"OH NO",
"b":"an insertion"
},
{
"a":1,
"b":1
}
]
const newArrays = ArrayCollide(arr1, arr2)
console.log(newArrays[0])
console.log(newArrays[1])
console.log('\n')
// []
// [ { a: 'OH NO', b: 'an insertion' } ]
// everything collided until this is left
//ObjectCollide
const obj1 = { a: '111', c: { q: 'no', a: '333' } }
const obj2 = { a: '111', p: 'ok', c: { a: '333' } }
ObjectCollide(obj1, obj2) //in place
console.log(obj1)
console.log(obj2)
console.log('\n')
// { c: { q: 'no' } }
// { p: 'ok', c: {} }
// obj["a"] collided and obj["c"]["a"] collided
//testing empty array
const a1 = { a: [] }
const a2 = { a: [], b: '2' }
ObjectCollide(a1, a2) //in place
console.log(a1)
console.log(a2)
console.log('\n')
// {}
// { b: '2' }
// obj["a"] collided
//DIFFERENT TYPES
const b1 = {a:true}
const b2 = {a:[1,2]}
ObjectCollide(b1,b2) //in place
console.log(b1)
console.log(b2)
// { a: true }
// { a: [ 1, 2 ] }
function ObjectCollide(obj1, obj2) {
//in place, returns true if same
// delete same
const keys = Object.keys(obj1)
const len = keys.length
let howManyDeleted = 0
for (let i = 0; i < len; i++) {
const key = keys[i]
const type1 = Array.isArray(obj1[key]) === true ? 'array' : typeof obj1[key]
const type2 = Array.isArray(obj2[key]) === true ? 'array' : typeof obj2[key]
if (type1!==type2) {
continue
}
switch (type1) {
case 'object':
if (ObjectCollide(obj1[key], obj2[key])) {
delete obj1[key]
delete obj2[key]
howManyDeleted++
}
continue
case 'array':
const newArrays = ArrayCollide(obj1[key], obj2[key])
if (newArrays) {
obj1[key] = newArrays[0]
obj2[key] = newArrays[1]
} else {
delete obj1[key]
delete obj2[key]
howManyDeleted++
}
continue
default:
//string, number, I hope it covers everything else
if (obj1[key] === obj2[key]) {
delete obj1[key]
delete obj2[key]
howManyDeleted++
}
}
}
if (howManyDeleted === len && Object.keys(obj2).length === 0) {
// return 'delete the stuff'
// same. we've deleted everything!
return true
}
}
function ArrayCollide(arr1, arr2) {
// returns [newArr1, newArr2] or false if same arrays (ignore order)
const stringifyObj = {}
const newArr1 = []
const newArr2 = []
for (let i = 0, len = arr1.length; i < len; i++) {
const value = arr1[i]
const stringified = JSON.stringify(value)
stringifyObj[stringified]
// arr = [count, ...]
const arr = stringifyObj[stringified] || (stringifyObj[stringified] = [0])
arr[0]++
arr.push(value)
}
//in 2 but not in 1
for (let i = 0, len = arr2.length; i < len; i++) {
const value = arr2[i]
const stringified = JSON.stringify(value)
const arr = stringifyObj[stringified]
if (arr === undefined) {
newArr2.push(value)
} else {
if (arr[0] === 0) {
newArr2.push(value)
} else {
arr[0]--
}
}
}
//in 1 but not in 2
stringifyKeys = Object.keys(stringifyObj)
for (let i = 0, len = stringifyKeys.length; i < len; i++) {
const arr = stringifyObj[stringifyKeys[i]]
for (let i = 1, len = arr[0] + 1; i < len; i++) {
newArr1.push(arr[i])
}
}
if (newArr1.length || newArr2.length) {
return [newArr1, newArr2]
} else {
return false
}
}
what I was trying to solve:
JSON file keeps reordering, I want to revert the JSON if it's equivalent: like {a:1,b:2}
and {b:2,a:1}
but because I don't trust my code (I made a mistake once), I want to see the diff and check it myself, I can Ctrl+F into the original file using this diff.
newObj
is generated by js code reading values from a form in the DOM. There are several ways to keep state and do this much easier, but I'd like to keep it stateless as an exercise. Also I am looking for prior art to see how others might have tackled this, if indeed anyone has. – Consciencearr.sort((a,b) => JSON.stringify(a).localeCompare(JSON.stringify(b)))
, do this for the original one and the modified one – Trinetta