DEV Community

Bukunmi Odugbesan
Bukunmi Odugbesan

Posted on

Coding Challenge Practice - Question 106

The task is to implement deep equal _isEqual.

The boilerplate code

function isEqual(a, b) {
  // your code here
}
Enter fullscreen mode Exit fullscreen mode

Handle primitive and reference equality

if (Object.is(a, b)) return true;
Enter fullscreen mode Exit fullscreen mode

Reject non-objects early

if(typeof a !== "object" || typeof b !== 'object' || a === null || b === null) { 
return false; 
}
Enter fullscreen mode Exit fullscreen mode

Track pairs already compared

const key = `${a}:${b}`;
if (seen.has(key)) {
  return true;
}
seen.set(key, true);
Enter fullscreen mode Exit fullscreen mode

Compare time values. Two different Date values can be equal

if (a instanceof Date && b instanceof Date) {
  return a.getTime() === b.getTime();
}
Enter fullscreen mode Exit fullscreen mode

Compare patterns and flags

if (a instanceof RegExp && b instanceof RegExp) {
  return a.toString() === b.toString();
}
Enter fullscreen mode Exit fullscreen mode

Sort objects that represent different structures

if (Array.isArray(a) !== Array.isArray(b)) return false;
Enter fullscreen mode Exit fullscreen mode

Objects with different numbers of properties cannot be equal

const keysA = Object.keys(a);
const keysB = Object.keys(b);

if (keysA.length !== keysB.length) {
  seen.delete(key);
  return false;
}
Enter fullscreen mode Exit fullscreen mode

seen.delete(key) ensures cleanup on failure.

Each property in one object must be present in the other. Each value should be compared recursively

for (const key of keysA) {
  if (!keysB.includes(key)) {
    seen.delete(key);
    return false;
  }

  if (!isEqual(a[key], b[key], seen)) {
    seen.delete(key);
    return false;
  }
}
Enter fullscreen mode Exit fullscreen mode

The final code

function isEqual(a, b, seen = new Map()) {
  // your code here
  if(Object.is(a,b)) return true;

  if(typeof a !== "object" || typeof b !== 'object' || a === null || b === null) {
    return false;
  }

  const key = `${a}:${b}`;
  if(seen.has(key)) {
    return true;
  }
  seen.set(key,true);

  if(a instanceof Date  && b instanceof Date) {
    return a.getTime() === b.getTime()
  }

  if(a instanceof RegExp && b instanceof RegExp) {
    return a.toString() === b.toString()
  }

  if(Array.isArray(a) !== Array.isArray(b)) return false;

  const keysA = Object.keys(a);
  const keysB = Object.keys(b);

  if(keysA.length !== keysB.length) {
    seen.delete(key);
    return false;
  };

  for(const key of keysA) {
    if(!keysB.includes(key)){
      seen.delete(key);
      return false;
    };
    if(!isEqual(a[key], b[key], seen)) {
      seen.delete(key);
      return false;
    };
  }
  seen.delete(key);
  return true;
}
Enter fullscreen mode Exit fullscreen mode

That's all folks!

Top comments (0)