Set and Map
Set and Map are ES6 data structures that provide alternatives to arrays and objects with enhanced functionality and better performance for specific use cases.
Set - Collection of Unique Values
Creating and Basic Operations
javascript// Creating Sets const emptySet = new Set(); const numbersSet = new Set([1, 2, 3, 4, 5]); const stringSet = new Set(['apple', 'banana', 'orange']); // From string (each character becomes an element) const charSet = new Set('hello'); // Set {'h', 'e', 'l', 'o'} console.log(numbersSet); // Set {1, 2, 3, 4, 5} console.log(numbersSet.size); // 5 // Adding values numbersSet.add(6); numbersSet.add(3); // Duplicate, won't be added console.log(numbersSet); // Set {1, 2, 3, 4, 5, 6} // Checking existence console.log(numbersSet.has(3)); // true console.log(numbersSet.has(10)); // false // Deleting values numbersSet.delete(3); console.log(numbersSet.has(3)); // false // Clear all values const tempSet = new Set([1, 2, 3]); tempSet.clear(); console.log(tempSet.size); // 0
Set Iteration
javascriptconst fruits = new Set(['apple', 'banana', 'orange', 'grape']); // for...of loop for (const fruit of fruits) { console.log(fruit); } // forEach method fruits.forEach(fruit => { console.log(`Fruit: ${fruit}`); }); // forEach with index (value is repeated as key in Sets) fruits.forEach((value, key, set) => { console.log(`${key}: ${value}`); // key === value for Sets }); // Convert to array const fruitsArray = [...fruits]; console.log(fruitsArray); // ['apple', 'banana', 'orange', 'grape'] // Array methods with Sets const upperFruits = [...fruits].map(fruit => fruit.toUpperCase()); console.log(upperFruits); // ['APPLE', 'BANANA', 'ORANGE', 'GRAPE']
Set Operations
javascriptconst setA = new Set([1, 2, 3, 4]); const setB = new Set([3, 4, 5, 6]); // Union (combine sets) const union = new Set([...setA, ...setB]); console.log(union); // Set {1, 2, 3, 4, 5, 6} // Intersection (common elements) const intersection = new Set([...setA].filter(x => setB.has(x))); console.log(intersection); // Set {3, 4} // Difference (elements in A but not in B) const difference = new Set([...setA].filter(x => !setB.has(x))); console.log(difference); // Set {1, 2} // Symmetric difference (elements in either A or B, but not both) const symmetricDiff = new Set([ ...[...setA].filter(x => !setB.has(x)), ...[...setB].filter(x => !setA.has(x)) ]); console.log(symmetricDiff); // Set {1, 2, 5, 6} // Subset check function isSubset(subset, superset) { return [...subset].every(value => superset.has(value)); } const smallSet = new Set([1, 2]); console.log(isSubset(smallSet, setA)); // true
Map - Key-Value Pairs
Creating and Basic Operations
javascript// Creating Maps const emptyMap = new Map(); const userMap = new Map([ ['name', 'John'], ['age', 30], ['city', 'New York'] ]); // Any type can be a key const mixedMap = new Map(); mixedMap.set('string', 'String key'); mixedMap.set(42, 'Number key'); mixedMap.set(true, 'Boolean key'); mixedMap.set({id: 1}, 'Object key'); mixedMap.set([1, 2], 'Array key'); console.log(userMap.size); // 3 // Setting values userMap.set('email', 'john@example.com'); userMap.set('age', 31); // Updates existing key // Getting values console.log(userMap.get('name')); // 'John' console.log(userMap.get('age')); // 31 console.log(userMap.get('phone')); // undefined // Checking existence console.log(userMap.has('email')); // true console.log(userMap.has('phone')); // false // Deleting entries userMap.delete('city'); console.log(userMap.has('city')); // false // Clear all entries const tempMap = new Map([['a', 1], ['b', 2]]); tempMap.clear(); console.log(tempMap.size); // 0
Map Iteration
javascriptconst scores = new Map([ ['Alice', 95], ['Bob', 87], ['Charlie', 92], ['Diana', 98] ]); // for...of with entries (default) for (const [name, score] of scores) { console.log(`${name}: ${score}`); } // for...of with keys for (const name of scores.keys()) { console.log(`Player: ${name}`); } // for...of with values for (const score of scores.values()) { console.log(`Score: ${score}`); } // forEach method scores.forEach((score, name) => { console.log(`${name} scored ${score}`); }); // Convert to arrays const entriesArray = [...scores]; // [['Alice', 95], ['Bob', 87], ...] const keysArray = [...scores.keys()]; // ['Alice', 'Bob', 'Charlie', 'Diana'] const valuesArray = [...scores.values()]; // [95, 87, 92, 98] // Convert to object const scoresObject = Object.fromEntries(scores); console.log(scoresObject); // {Alice: 95, Bob: 87, Charlie: 92, Diana: 98}
Advanced Map Usage
javascript// Using objects as keys const user1 = {id: 1, name: 'Alice'}; const user2 = {id: 2, name: 'Bob'}; const userPreferences = new Map(); userPreferences.set(user1, {theme: 'dark', language: 'en'}); userPreferences.set(user2, {theme: 'light', language: 'es'}); console.log(userPreferences.get(user1)); // {theme: 'dark', language: 'en'} // WeakMap for garbage collection (keys must be objects) const weakMap = new WeakMap(); let obj = {data: 'important'}; weakMap.set(obj, 'metadata'); // When obj is garbage collected, the WeakMap entry is automatically removed // Chaining operations const chainMap = new Map() .set('a', 1) .set('b', 2) .set('c', 3); console.log(chainMap); // Map {'a' => 1, 'b' => 2, 'c' => 3}
Practical Examples
Remove Duplicates from Array
javascriptfunction removeDuplicates(array) { return [...new Set(array)]; } const numbers = [1, 2, 2, 3, 4, 4, 5]; console.log(removeDuplicates(numbers)); // [1, 2, 3, 4, 5] const words = ['apple', 'banana', 'apple', 'orange', 'banana']; console.log(removeDuplicates(words)); // ['apple', 'banana', 'orange']
Frequency Counter
javascriptfunction countFrequency(array) { const frequency = new Map(); for (const item of array) { frequency.set(item, (frequency.get(item) || 0) + 1); } return frequency; } const letters = ['a', 'b', 'a', 'c', 'b', 'a']; const letterCount = countFrequency(letters); console.log(letterCount); // Map {'a' => 3, 'b' => 2, 'c' => 1} // Find most frequent item function findMostFrequent(array) { const frequency = countFrequency(array); let maxCount = 0; let mostFrequent = null; for (const [item, count] of frequency) { if (count > maxCount) { maxCount = count; mostFrequent = item; } } return {item: mostFrequent, count: maxCount}; } console.log(findMostFrequent(letters)); // {item: 'a', count: 3}
Cache Implementation
javascriptclass LRUCache { constructor(capacity) { this.capacity = capacity; this.cache = new Map(); } get(key) { if (this.cache.has(key)) { // Move to end (most recently used) const value = this.cache.get(key); this.cache.delete(key); this.cache.set(key, value); return value; } return -1; } put(key, value) { if (this.cache.has(key)) { // Update existing key this.cache.delete(key); } else if (this.cache.size >= this.capacity) { // Remove least recently used (first item) const firstKey = this.cache.keys().next().value; this.cache.delete(firstKey); } this.cache.set(key, value); } display() { console.log([...this.cache]); } } const cache = new LRUCache(3); cache.put('a', 1); cache.put('b', 2); cache.put('c', 3); cache.display(); // [['a', 1], ['b', 2], ['c', 3]] cache.get('a'); // Access 'a' cache.put('d', 4); // This will remove 'b' cache.display(); // [['c', 3], ['a', 1], ['d', 4]]
Group Array Elements
javascriptfunction groupBy(array, keyFn) { const groups = new Map(); for (const item of array) { const key = keyFn(item); if (!groups.has(key)) { groups.set(key, []); } groups.get(key).push(item); } return groups; } const people = [ {name: 'Alice', age: 25, city: 'NYC'}, {name: 'Bob', age: 30, city: 'LA'}, {name: 'Charlie', age: 25, city: 'NYC'}, {name: 'Diana', age: 30, city: 'Chicago'} ]; // Group by age const byAge = groupBy(people, person => person.age); console.log(byAge); // Map {25 => [{name: 'Alice', ...}, {name: 'Charlie', ...}], 30 => [...]} // Group by city const byCity = groupBy(people, person => person.city); console.log(byCity);
Set-based Algorithms
javascript// Find unique elements across multiple arrays function findUniqueAcrossArrays(...arrays) { const allElements = new Set(); const duplicates = new Set(); for (const array of arrays) { for (const element of array) { if (allElements.has(element)) { duplicates.add(element); } else { allElements.add(element); } } } return [...allElements].filter(element => !duplicates.has(element)); } const arr1 = [1, 2, 3, 4]; const arr2 = [3, 4, 5, 6]; const arr3 = [5, 6, 7, 8]; console.log(findUniqueAcrossArrays(arr1, arr2, arr3)); // [1, 2, 7, 8] // Check if arrays have common elements function hasCommonElements(arr1, arr2) { const set1 = new Set(arr1); return arr2.some(element => set1.has(element)); } console.log(hasCommonElements([1, 2, 3], [4, 5, 6])); // false console.log(hasCommonElements([1, 2, 3], [3, 4, 5])); // true
Performance Comparison
javascript// Performance comparison: Set vs Array for lookups function performanceTest() { const size = 100000; const array = Array.from({length: size}, (_, i) => i); const set = new Set(array); const searchValue = size - 1; // Worst case for array // Array lookup console.time('Array includes'); array.includes(searchValue); console.timeEnd('Array includes'); // Set lookup console.time('Set has'); set.has(searchValue); console.timeEnd('Set has'); // Map vs Object for key-value operations const obj = {}; const map = new Map(); // Adding properties/entries console.time('Object property assignment'); for (let i = 0; i < 10000; i++) { obj[`key${i}`] = i; } console.timeEnd('Object property assignment'); console.time('Map set'); for (let i = 0; i < 10000; i++) { map.set(`key${i}`, i); } console.timeEnd('Map set'); } // performanceTest(); // Uncomment to run performance test