Creating Copies of Maps and Sets in JavaScript: A Comprehensive Guide


Welcome, fellow coders! Today, we’ll explore various ways to create copies of Maps and Sets in Javascript. Buckle up and get ready for a ride through deep and shallow copies of Maps and Sets, using plain JavaScript and even some help from the lodash library.


Create a Deep Copy of a Map in JavaScript

Using JSON.stringify and JSON.parse

Creating a deep copy involves converting the Map to an array, stringifying it, and then parsing it back. Here’s the code:

JavaScript
const existingMap = new Map([
  ['address', { street: 'Example' }],
  ['numbers', [1, 2, 3]],
]);

const deepCopy = new Map(JSON.parse(JSON.stringify(Array.from(existingMap))));

console.log(deepCopy);

This method ensures that nested objects or arrays in the Map lose their reference, preventing unwanted side effects.

Using Lodash Library

For those who prefer simplicity and elegance, lodash has us covered:

JavaScript
import _ from 'lodash';

const existingMap = new Map([
  ['address', { street: 'Example' }],
  ['numbers', [1, 2, 3]],
]);

const deepCopy = _.cloneDeep(existingMap);

console.log(deepCopy);

Lodash’s cloneDeep method makes the process clean and concise, ensuring a deep copy without shared references.


Create a Deep Copy of a Set in JavaScript

Using JSON.stringify and JSON.parse (Set)

The process for creating a deep copy of a Set mirrors that of a Map:

JavaScript
const existingSet = new Set([[1, 2, 3]]);

const deepCopy = new Set(JSON.parse(JSON.stringify(Array.from(existingSet))));

console.log(deepCopy);

Stringifying and parsing ensure that nested objects or arrays within the Set lose their reference, maintaining the integrity of the deep copy.

Using Lodash Library (Set)

Lodash provides a convenient method for deep copying Sets as well:

JavaScript
import _ from 'lodash';

const existingSet = new Set([[1, 2, 3]]);

const deepCopy = _.cloneDeep(existingSet);

console.log(deepCopy);

Utilizing cloneDeep from lodash ensures a clean and reliable deep copy operation.


Create a Shallow Copy of a Map in JavaScript

Using Map Constructor

For a less complex scenario where a shallow copy suffices, the Map constructor can be our friend:

JavaScript
const oldMap = new Map([
  ['name', 'bobby hadz'],
  ['country', 'Chile'],
]);

const copy = new Map();

oldMap.forEach((value, key) => {
  copy.set(key, value);
});

console.log(copy);

The Map constructor takes an iterable, such as another Map, and adds its key-value pairs to the new Map, providing a straightforward solution.

Using Map.forEach

An alternative method involves manually iterating over the original Map and populating the new one:

JavaScript
const oldMap = new Map([
  ['name', 'bobby hadz'],
  ['country', 'Chile'],
]);

const copy = new Map();

oldMap.forEach((value, key) => {
  copy.set(key, value);
});

console.log(copy);

This approach allows more control during iteration and is particularly useful when additional logic is needed.


Create a Shallow Copy of a Set in JavaScript

Using Set Constructor

Creating a shallow copy of a Set can be achieved effortlessly with the Set constructor:

JavaScript
const set1 = new Set(['coding', 'with', 'piyush']);

const cloned = new Set(set1);

console.log(cloned);

The Set constructor takes an iterable, such as another Set, and adds all unique elements to the new Set, providing a straightforward solution.

Using for…of Loop

A manual approach involves using a for…of loop to iterate over the original Set and populate the new one:

JavaScript
const set1 = new Set(['coding', 'with', 'piyush']);

const cloned = new Set();

for (const element of set1) {
  cloned.add(element);
}

console.log(cloned);

This method allows more flexibility during iteration, enabling additional logic if needed.


🧪Practice Coding Problem: Deep Copy Function for a Map

In the spirit of Test Driven Development ( 😁), lets test our understanding by solving a problem.

Write a function deepCopyMap that takes a Map as input and returns a deep copy of the Map. The deep copy should ensure that any nested objects or arrays within the Map do not share references with the original Map.

JavaScript
/**
 * Deep copy function for a Map
 * @param {Map} map - The Map to be deep copied
 * @returns {Map} - The deep copy of the input Map
 */
function deepCopyMap(map) {
  // > > > 👉 Write code here 👈 < < <
}

// Example usage:
const originalMap = new Map([
  ['user', { name: 'John', age: 25 }],
  ['scores', [90, 85, 92]],
]);

const copiedMap = deepCopyMap(originalMap);

// Modify the copied Map and ensure the original Map is not affected
copiedMap.get('user').age = 30;

console.log(originalMap.get('user').age); // Should not change (remains 25)
console.log(copiedMap.get('user').age);   // Should be 30
Please attempt before seeing the Answer:
JavaScript
/*
1. Edge case: array or objs in map should be deep copies, so not shared between the original and copied Map.
2. So, use a `deepCopy` helper function for objects and arrays. 
3. The deepCopyMap function then uses this helper to create a deep copy of the original Map.

*/

/**
 * Deep copy function for a Map
 * @param {Map} map - The Map to be deep copied
 * @returns {Map} - The deep copy of the input Map
 */
function deepCopyMap(map) {
  const deepCopiedMap = new Map();

  // Iterate over the original Map entries
  map.forEach((value, key) => {
    // Check if the value is an object or array to perform a deep copy
    const copiedValue = typeof value === 'object' ? deepCopy(value) : value;
    deepCopiedMap.set(key, copiedValue);
  });

  return deepCopiedMap;
}

/**
 * Deep copy Helper function for objects and arrays special cases
 * @param {Object|Array} obj - The object or array to be deep copied
 * @returns {Object|Array} - The deep copy of the input object or array
 */
function deepCopy(obj) {
  if (Array.isArray(obj)) {
    // Deep copy for arrays
    return obj.map((item) => (typeof item === 'object' ? deepCopy(item) : item));
  } else if (obj !== null && typeof obj === 'object') {
    // Deep copy for objects
    const copiedObj = {};
    for (const [key, value] of Object.entries(obj)) {
      copiedObj[key] = typeof value === 'object' ? deepCopy(value) : value;
    }
    return copiedObj;
  } else {
    // Base case: non-object values
    return obj;
  }
}

Conclusion:

In this comprehensive guide, we explored how to creating deep and shallow copies of Maps and Sets in JavaScript. From using native JavaScript, to leveraging lodash library, you have seen it all, my copy-cat. 😹

Remember, the choice between deep and shallow copies depends on your specific requirements: are you safeguarding against unintended mutations or simply creating a lightweight clone, understanding these techniques is also crucial for Functional Programming.

Happy coding! 🚀

Scroll to Top