https://bigfrontend.dev/problem/find-corresponding-node-in-two-identical-DOM-tree
Given two same DOM tree A, B, and an Element a in A, find the corresponding Element b in B.
By corresponding, we mean a and b have the same relative position to their DOM tree root.
follow up
This could a problem on general Tree structure with only children
.
Could you solve it recursively and iteratively?
Could you solve this problem both with special DOM api for better performance?
What are the time cost for each solution?
/**
* @param {HTMLElement} rootA
* @param {HTMLElement} rootB - rootA and rootB are clone of each other
* @param {HTMLElement} nodeA
*/
const findCorrespondingNode = (rootA, rootB, targetNode) => {
if (rootA === targetNode) {
return rootB;
}
for (let i = 0; i < rootA.childNodes.length; i++) {
const result = findCorrespondingNode(
rootA.childNodes[i],
rootB.childNodes[i],
targetNode
);
if (result) {
return result;
}
}
return null;
};
/**
* @param {HTMLElement} rootA
* @param {HTMLElement} rootB - rootA and rootB are clone of each other
* @param {HTMLElement} nodeA
*/
const findCorrespondingNode = (rootA, rootB, target) => {
let stackA = [rootA];
let stackB = [rootB];
while (stackA.length > 0) {
const nodeA = stackA.pop();
const nodeB = stackB.pop();
if (nodeA === target) {
return nodeB;
}
stackA.push(...nodeA.childNodes);
stackB.push(...nodeB.childNodes);
}
return;
};
/**
* @param {HTMLElement} rootA
* @param {HTMLElement} rootB - rootA and rootB are clone of each other
* @param {HTMLElement} nodeA
*/
const findCorrespondingNode = (rootA, rootB, target) => {
const path = [];
let node = target;
while (node !== rootA) {
const parentNode = node.parentNode;
const childNodes = Array.from(parentNode.childNodes);
path.push(childNodes.indexOf(node));
node = parentNode;
}
return path.reduceRight((node, index) => node.childNodes[index], rootB);
};
const rootA = {
value: "A",
childNodes: [
{
value: "B",
childNodes: [
{
value: "C",
childNodes: [],
},
],
},
],
};
const rootB = {
value: "A",
childNodes: [
{
value: "B",
childNodes: [
{
value: "C",
childNodes: [],
},
],
},
],
};
const targetNode = rootA.childNodes[0].childNodes[0];
console.log(findCorrespondingNode(rootA, rootB, targetNode));
Let's break down the findCorrespondingNode
function and its usage:
-
Function Definition: The
findCorrespondingNode
function takes three arguments:nodeA
,nodeB
, andtargetNode
. It's designed to find a node innodeB
that corresponds totargetNode
innodeA
, assumingnodeA
andnodeB
have the same structure. -
Base Cases: If
nodeA
is thetargetNode
, it returnsnodeB
. IfnodeA
has no child nodes, it returnsnull
because there's no corresponding node innodeB
. -
Recursion: If
nodeA
is not thetargetNode
and it has child nodes, it recursively callsfindCorrespondingNode
for each pair of child nodes innodeA
andnodeB
. If a recursive call returns a non-null result, it returns that result. -
Usage: The usage example creates two identical tree structures
nodeA
andnodeB
, each with a root node and a single child node that also has a single child node. It then callsfindCorrespondingNode
withnodeA
,nodeB
, and the first child node ofnodeA
as thetargetNode
. -
Output: The output of the function call is the first child node of
nodeB
, which corresponds to thetargetNode
innodeA
. This is logged to the console.
This findCorrespondingNode
function can be used to find corresponding nodes in two tree structures that have the same structure. It uses a depth-first search strategy, checking the current node before checking the child nodes.