cielux
10/24/2018 - 12:17 AM

DOM Equal

Question 1: DOM Equality DOM Nodes are “DOM Equal” if they have the same number of descendant elements of every type. For example:

is equal to:

Step 1: Please implement the following function: function areEqual(element1, element2) Which returns true when the elements are DOM Equal

Step 2: Given an element, please implement the following function: function equalElements(element) Which returns all the equality groups. Equality group is defined as a list of all descendant elements which are DOM Equal [[elem1, elem2], ...]

function getAllDescendants(element) {
  let descendants = [];
  for (const child of element.children) {
    descendants.push(child.tagName);
    descendants.push(...getAllDescendants(child));
  }
  // Now we have the fingerprint
  // Add `element` to the global table of elements with that fingerprint
  return descendants;
}

function arrayEqual(array1, array2) {
  array1.sort();
  array2.sort();
  return (array1.length === array2.length) && (array1.every((val, idx) => val === array2[idx]));
}

function areEqual(element1, element2) {
  const descendants1 = getAllDescendants(element1);
  const descendants2 = getAllDescendants(element2);
  
  return arrayEqual(descendants1, descendants2);
}

function equalElements(element) {
  
}

// max solution:

function tabAdd(tab, key, val = 1) {
  if (!tab.hasOwnProperty(key)) {
    tab[key] = 0;
  }
  tab[key] += val;
}

function serializeFingerprint(table) {
  const keys = Object.keys(table);
  keys.sort();
  const list = [];
  for (const key of keys) {
    list.push([key, table[key]]);
  }
  return JSON.stringify(list);
}

function tabMerge(a, b) {
  const bKeys = Object.keys(b);
  for (const key of bKeys) {
    tabAdd(a, key, b[key]);
  }
}

function getFingerprint(element, fingerprintGroups) {
  const fingerprint = {};
  for (const child of element.children) {
    tabAdd(fingerprint, child.tagName);
    const childFingerprint = getFingerprint(child, fingerprintGroups);
    tabMerge(fingerprint, childFingerprint);
  }
  if (fingerprintGroups) {
    const serializedFingerprint = serializeFingerprint(fingerprint);
    if (!fingerprintGroups.hasOwnProperty(serializedFingerprint)) {
      fingerprintGroups[serializedFingerprint] = [];
    }
    fingerprintGroups[serializedFingerprint].push(element);
  }
  return fingerprint;
}

function fingerprintsEqual(a, b) {
  const tags1 = Object.keys(a), tags2 = Object.keys(b);
  return (tags1.length === tags2.length) && (tags1.every(tag => a[tag] === b[tag]));
}

function maxAreEqual(element1, element2) {
  return fingerprintsEqual(
    getFingerprint(element1),
    getFingerprint(element2)
  );
}

function maxEqualElements(element) {
  const equalityGroups = {};
  for (const child of element.children) {
    getFingerprint(child, equalityGroups);
  }
  return Object.values(equalityGroups);
}

// Tests

const parent = document.getElementById('parent');
const element1 = document.getElementById('1');
const element2 = document.getElementById('2');
console.log('areEqual', areEqual(element1, element2));

console.log('maxAreEqual', maxAreEqual(element1, element2));
console.log('maxEqualElements', maxEqualElements(parent));