From 8a4a42918c41ac1359cca4997b5d92bf81414016 Mon Sep 17 00:00:00 2001 From: Veda Vyasa <2400040217@kluniversity.in> Date: Wed, 19 Nov 2025 16:25:09 +0530 Subject: [PATCH 1/4] feat: Add deep-merge nested objects exercise with circular reference handling --- coding-exercise/deep-merge-nested-objects.md | 49 ++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 coding-exercise/deep-merge-nested-objects.md diff --git a/coding-exercise/deep-merge-nested-objects.md b/coding-exercise/deep-merge-nested-objects.md new file mode 100644 index 00000000..12126285 --- /dev/null +++ b/coding-exercise/deep-merge-nested-objects.md @@ -0,0 +1,49 @@ +# Exercise: Deep-Merge Two Nested Objects With Circular References + +### Problem Statement + +Write a function **`deepMerge(objA, objB)`** that merges two JavaScript objects **without mutating** either of the original objects. + +The function must follow these rules: + +1. If a property exists in only one object, take that value. +2. If the property exists in both objects: + - If both values are **plain objects**, recursively merge them. + - If both values are **arrays**, concatenate them. + - Otherwise, the value from **objB** overwrites the one from **objA**. +3. Handle **circular references** safely. + If you encounter the same reference path again, avoid infinite recursion. +4. Ensure the merge is **immutable** — return a **new** object. +5. Ensure the solution runs in **O(n)** time where *n* is the total number of properties. + +--- + +### Example: + +```js +const a = { + x: { y: 1 }, + arr: [1, 2], +}; +a.self = a; // Circular reference + +const b = { + x: { z: 2 }, + arr: [3], + extra: true +}; +b.loop = b; // Circular reference + +const result = deepMerge(a, b); + +/* +Expected structure: + +{ + x: { y: 1, z: 2 }, + arr: [1, 2, 3], + extra: true, + self: , + loop: +} +*/ From 76c3ca7a47f9cc2d35fb7f06073906d04b33f70e Mon Sep 17 00:00:00 2001 From: Vedavyasa Date: Thu, 20 Nov 2025 20:07:48 +0530 Subject: [PATCH 2/4] Changed Variable names --- coding-exercise/deep-merge-nested-objects.md | 37 ++++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/coding-exercise/deep-merge-nested-objects.md b/coding-exercise/deep-merge-nested-objects.md index 12126285..d4bfb3e7 100644 --- a/coding-exercise/deep-merge-nested-objects.md +++ b/coding-exercise/deep-merge-nested-objects.md @@ -6,38 +6,36 @@ Write a function **`deepMerge(objA, objB)`** that merges two JavaScript objects The function must follow these rules: -1. If a property exists in only one object, take that value. -2. If the property exists in both objects: +1. If a property exists only in one object, return that value. +2. If both objects contain the same key: - If both values are **plain objects**, recursively merge them. - If both values are **arrays**, concatenate them. - - Otherwise, the value from **objB** overwrites the one from **objA**. -3. Handle **circular references** safely. - If you encounter the same reference path again, avoid infinite recursion. -4. Ensure the merge is **immutable** — return a **new** object. -5. Ensure the solution runs in **O(n)** time where *n* is the total number of properties. + - Otherwise, the value from **objB** overwrites the value from **objA**. +3. Handle **circular references** safely using a `WeakMap` to track already merged objects. +4. The merge must be **immutable** — return a **new** object. --- -### Example: +### Example ```js -const a = { - x: { y: 1 }, - arr: [1, 2], +const firstObject = { + x: { y: 1 }, + arr: [1, 2], }; -a.self = a; // Circular reference +firstObject.self = firstObject; // Circular reference -const b = { - x: { z: 2 }, - arr: [3], - extra: true +const secondObject = { + x: { z: 2 }, + arr: [3], + extra: true, }; -b.loop = b; // Circular reference +secondObject.loop = secondObject; // Circular reference -const result = deepMerge(a, b); +const result = deepMerge(firstObject, secondObject); /* -Expected structure: +Expected output: { x: { y: 1, z: 2 }, @@ -47,3 +45,4 @@ Expected structure: loop: } */ + From 92ce5720476509cd3d7369966ef80811c2ad2718 Mon Sep 17 00:00:00 2001 From: Veda Vyasa <2400040217@kluniversity.in> Date: Mon, 24 Nov 2025 11:25:55 +0530 Subject: [PATCH 3/4] fix: Align question.md with README and solution structure --- .../deep-merge-nested-objects/README.md | 62 +++++++++++++++++++ .../deep-merge-nested-objects/question.md | 51 +++++++++++++++ .../deep-merge-nested-objects/solution.js | 50 +++++++++++++++ 3 files changed, 163 insertions(+) create mode 100644 coding-exercise/deep-merge-nested-objects/README.md create mode 100644 coding-exercise/deep-merge-nested-objects/question.md create mode 100644 coding-exercise/deep-merge-nested-objects/solution.js diff --git a/coding-exercise/deep-merge-nested-objects/README.md b/coding-exercise/deep-merge-nested-objects/README.md new file mode 100644 index 00000000..253be514 --- /dev/null +++ b/coding-exercise/deep-merge-nested-objects/README.md @@ -0,0 +1,62 @@ +Deep-Merge Two Nested Objects (with Circular References) +Challenge: +Implement a deep-merge function that combines two nested JavaScript objects while safely handling circular references. The function must be immutable and able to merge objects, arrays, and nested structures. + +Problem Description: +Deep merging means recursively combining the properties of two objects. When both inputs contain nested objects, arrays, or shared references, this becomes more complex. + +Your task is to: +Merge all properties from both objects +Recursively merge nested objects +Merge arrays by index +Avoid infinite recursion when circular references exist +Return a new, immutable object +Ensure values from the second object override the first when conflicts occur +Real-World Use Case +State management libraries (Redux, Zustand, Immer) +Complex configuration merging +Deep cloning with overrides +Normalizing API responses +Merging schema definitions + +Example: +Input +const a = { + x: 1, + y: { z: 2 } +}; +a.self = a; // circular reference + +const b = { + y: { k: 20 }, + m: 100 +}; +b.loop = b; // circular reference + +const result = deepMerge(a, b); + +Output +{ + x: 1, + y: { z: 2, k: 20 }, + m: 100, + self: [circular], + loop: [circular] +} + +Requirements: +Must deep-merge nested objects and arrays +Must detect and safely handle circular references +Must not mutate inputs +When both objects contain the same key: +If both values are objects → recursively merge +If both are arrays → merge by index +Otherwise → value from second object overrides +Must create a brand-new object as the output + +Key Concepts: +Recursion +WeakMap to track visited nodes +Object and array cloning +Circular reference detection +Immutability principles \ No newline at end of file diff --git a/coding-exercise/deep-merge-nested-objects/question.md b/coding-exercise/deep-merge-nested-objects/question.md new file mode 100644 index 00000000..fd414103 --- /dev/null +++ b/coding-exercise/deep-merge-nested-objects/question.md @@ -0,0 +1,51 @@ +# Exercise: Deep-Merge Two Nested Objects (with Circular References) + +## Problem Statement + +Write a function **`deepMerge(objA, objB)`** that deeply merges two JavaScript objects **without mutating** either of them. +The function must correctly merge nested structures and safely handle circular references. + +--- + +## Rules + +1. If a key exists only in one object → copy that value. +2. If a key exists in both objects: + - If both values are **plain objects**, recursively merge them. + - If both values are **arrays**, merge by index (element-wise). + - Otherwise, the value from **`objB`** overrides the value from **`objA`**. +3. Handle **circular references** using a tracking mechanism like **WeakMap**. +4. Always return a **new**, immutable object. +5. Must preserve structure even when circular references appear on both inputs. + +--- + +## Example + +```js +const a = { + x: { y: 1 }, + arr: [1, 2] +}; +a.self = a; // circular + +const b = { + x: { z: 2 }, + arr: [3], + extra: true +}; +b.loop = b; // circular + +const result = deepMerge(a, b); + +/* +Expected structure: + +{ + x: { y: 1, z: 2 }, + arr: [1, 3], // merged by index + extra: true, + self: , + loop: +} +*/ diff --git a/coding-exercise/deep-merge-nested-objects/solution.js b/coding-exercise/deep-merge-nested-objects/solution.js new file mode 100644 index 00000000..3362907a --- /dev/null +++ b/coding-exercise/deep-merge-nested-objects/solution.js @@ -0,0 +1,50 @@ +/** + * Deeply merges two objects while safely handling circular references. + * Returns a new object without mutating the originals. + * + * @param {Object|Array} obj1 + * @param {Object|Array} obj2 + * @returns {Object|Array} + */ +function deepMerge(obj1, obj2, visited = new WeakMap()) { + // If obj2 is primitive, return it directly + if (obj2 === null || typeof obj2 !== "object") { + return obj2; + } + + // Detect circular reference + if (visited.has(obj2)) { + return visited.get(obj2); + } + + // Determine output type + const output = Array.isArray(obj1) ? [...obj1] : + Array.isArray(obj2) ? [...obj2] : + { ...obj1 }; + + visited.set(obj2, output); + + for (const key in obj2) { + if (!obj2.hasOwnProperty(key)) continue; + + const val1 = obj1 ? obj1[key] : undefined; + const val2 = obj2[key]; + + if (val1 !== undefined && typeof val1 === "object" && typeof val2 === "object") { + output[key] = deepMerge(val1, val2, visited); + } else { + output[key] = val2; + } + } + + return output; +} + +// Example usage +const a = { x: 1, y: { z: 2 } }; +a.self = a; + +const b = { y: { k: 20 }, m: 100 }; +b.loop = b; + +console.log(deepMerge(a, b)); From 3aa8ca1ebe343fc0909a9483fa05595775484e6b Mon Sep 17 00:00:00 2001 From: Veda Vyasa <2400040217@kluniversity.in> Date: Mon, 24 Nov 2025 11:27:29 +0530 Subject: [PATCH 4/4] chore: remove old deep-merge markdown file --- coding-exercise/deep-merge-nested-objects.md | 48 -------------------- 1 file changed, 48 deletions(-) delete mode 100644 coding-exercise/deep-merge-nested-objects.md diff --git a/coding-exercise/deep-merge-nested-objects.md b/coding-exercise/deep-merge-nested-objects.md deleted file mode 100644 index d4bfb3e7..00000000 --- a/coding-exercise/deep-merge-nested-objects.md +++ /dev/null @@ -1,48 +0,0 @@ -# Exercise: Deep-Merge Two Nested Objects With Circular References - -### Problem Statement - -Write a function **`deepMerge(objA, objB)`** that merges two JavaScript objects **without mutating** either of the original objects. - -The function must follow these rules: - -1. If a property exists only in one object, return that value. -2. If both objects contain the same key: - - If both values are **plain objects**, recursively merge them. - - If both values are **arrays**, concatenate them. - - Otherwise, the value from **objB** overwrites the value from **objA**. -3. Handle **circular references** safely using a `WeakMap` to track already merged objects. -4. The merge must be **immutable** — return a **new** object. - ---- - -### Example - -```js -const firstObject = { - x: { y: 1 }, - arr: [1, 2], -}; -firstObject.self = firstObject; // Circular reference - -const secondObject = { - x: { z: 2 }, - arr: [3], - extra: true, -}; -secondObject.loop = secondObject; // Circular reference - -const result = deepMerge(firstObject, secondObject); - -/* -Expected output: - -{ - x: { y: 1, z: 2 }, - arr: [1, 2, 3], - extra: true, - self: , - loop: -} -*/ -