1

I have two objects, for example:

const objA = {
  any: 'string',
  some: {
    prop: [
      {a: 1, b: 2},
      {a: 3, b: 4}
    ],
  }
};

const objB = {
  some: {
    prop: [
      {a: 3, b: 4},
      {a: 1, b: 2}
    ],
  },
  any: 'string'
};

I'd like to have a comparing method them so that the result in this case would be that these objects are equal. So, it needs to be a deep comparison and if an array occurs, the method would compare the objects inside this array, disregarding the order of objects in the array.

I tried to use the lodash isEqual function but it checks the array elements order as well. What would be the best solution?

Hubert Kubiak
  • 607
  • 1
  • 7
  • 30

2 Answers2

5

Using _.isEqualWith()

const objA = {"any":"string","some":{"prop":[{"a":1,"b":2},{"a":3,"b":4}]}}

const objB = {"some":{"prop":[{"a":3,"b":4},{"a":1,"b":2}]},"any":"string"}

let equal = _.isEqualWith(objA, objB, (a, b) => {
  if (Array.isArray(a)) return _(a).xorWith(b, _.isEqual).isEmpty()
})

console.log(equal)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
User863
  • 19,346
  • 2
  • 17
  • 41
1

You could turn the objects into strings and sort objects properties by key, and arrays by their contents strings.

const objHash = obj => {
  if(typeof obj !== "object" || obj === null)
   return JSON.stringify(obj);
   
  if(Array.isArray(obj))
    return "[" + obj.map(objHash).sort().join(",") + "]";
    
  return "{" + Object.entries(obj).sort(([kA], [kB]) => kA.localeCompare(kB)).map(([k, v]) => k + ":" + objHash(v)).join(",") + "}";
}
    

const objA = {
  some: {
    prop: [
      {a: 1, b: 2},
      {a: 3, b: 4}
    ],
  },
  any: 'string'
};

const objB = {
  some: {
    prop: [
      {a: 3, b: 4},
      {a: 1, b: 2}
    ],
  },
  any: 'string'
};

console.log("objA: ", objHash(objA));
console.log("objB: ", objHash(objB));
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151