Question 1: DOM Equality DOM Nodes are “DOM Equal” if they have the same number of descendant elements of every type. For example:
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));