javascript

examples

examples.js
/**
 * 6.3 Maps and Sets - Examples
 * ES6 Collection Data Structures
 */

// ============================================
// MAP EXAMPLES
// ============================================

console.log('=== Map Basics ===');

// Creating a Map
const map = new Map();

// Setting values with any key type
map.set('string', 'string key');
map.set(123, 'number key');
map.set(true, 'boolean key');
map.set(null, 'null key');

const objKey = { id: 1 };
const funcKey = () => {};
map.set(objKey, 'object key');
map.set(funcKey, 'function key');

console.log('Map size:', map.size);
console.log('Get string key:', map.get('string'));
console.log('Get object key:', map.get(objKey));
console.log('Has number key:', map.has(123));

// ============================================
// MAP INITIALIZATION
// ============================================

console.log('\n=== Map Initialization ===');

// From array of pairs
const users = new Map([
  ['u1', { name: 'Alice', age: 30 }],
  ['u2', { name: 'Bob', age: 25 }],
  ['u3', { name: 'Charlie', age: 35 }],
]);

console.log('Users map:', users);

// From Object
const config = { host: 'localhost', port: 3000, debug: true };
const configMap = new Map(Object.entries(config));
console.log('Config as Map:', configMap);

// Back to Object
const configObj = Object.fromEntries(configMap);
console.log('Back to Object:', configObj);

// ============================================
// MAP ITERATION
// ============================================

console.log('\n=== Map Iteration ===');

const scores = new Map([
  ['Alice', 95],
  ['Bob', 87],
  ['Charlie', 92],
]);

// for...of with destructuring
console.log('Entries:');
for (const [name, score] of scores) {
  console.log(`  ${name}: ${score}`);
}

// Keys only
console.log('Keys:', [...scores.keys()]);

// Values only
console.log('Values:', [...scores.values()]);

// forEach
scores.forEach((score, name) => {
  console.log(`forEach: ${name} scored ${score}`);
});

// ============================================
// SET BASICS
// ============================================

console.log('\n=== Set Basics ===');

const set = new Set();
set.add(1);
set.add(2);
set.add(2); // Duplicate - ignored
set.add(3);
set.add('hello');
set.add({ x: 1 });

console.log('Set size:', set.size); // 5 (not 6)
console.log('Has 2:', set.has(2));
console.log('Set contents:', [...set]);

// ============================================
// REMOVING DUPLICATES (Common Pattern!)
// ============================================

console.log('\n=== Remove Duplicates ===');

const arrayWithDupes = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5];
const uniqueArray = [...new Set(arrayWithDupes)];
console.log('Original:', arrayWithDupes);
console.log('Unique:', uniqueArray);

// With strings
const words = ['apple', 'banana', 'apple', 'cherry', 'banana'];
const uniqueWords = [...new Set(words)];
console.log('Unique words:', uniqueWords);

// ============================================
// SET OPERATIONS
// ============================================

console.log('\n=== Set Operations ===');

const setA = new Set([1, 2, 3, 4, 5]);
const setB = new Set([4, 5, 6, 7, 8]);

// Union (all elements from both)
const union = new Set([...setA, ...setB]);
console.log('Union:', [...union]);

// Intersection (common elements)
const intersection = new Set([...setA].filter((x) => setB.has(x)));
console.log('Intersection:', [...intersection]);

// Difference (A - B)
const difference = new Set([...setA].filter((x) => !setB.has(x)));
console.log('Difference (A-B):', [...difference]);

// Symmetric Difference (elements in A or B but not both)
const symDiff = new Set([
  ...[...setA].filter((x) => !setB.has(x)),
  ...[...setB].filter((x) => !setA.has(x)),
]);
console.log('Symmetric Difference:', [...symDiff]);

// Is Subset
const isSubset = [...setA].every((x) => setB.has(x));
console.log('A is subset of B:', isSubset);

// ============================================
// WEAKMAP EXAMPLES
// ============================================

console.log('\n=== WeakMap Examples ===');

const weakMap = new WeakMap();

let user = { id: 1, name: 'Alice' };
let settings = { id: 2, name: 'Settings' };

weakMap.set(user, { lastLogin: new Date(), visits: 5 });
weakMap.set(settings, { theme: 'dark' });

console.log('User data:', weakMap.get(user));
console.log('Has user:', weakMap.has(user));

// Private data pattern
const privateData = new WeakMap();

class BankAccount {
  constructor(owner, balance) {
    this.owner = owner;
    // Store balance privately
    privateData.set(this, { balance });
  }

  getBalance() {
    return privateData.get(this).balance;
  }

  deposit(amount) {
    const data = privateData.get(this);
    data.balance += amount;
  }

  withdraw(amount) {
    const data = privateData.get(this);
    if (amount > data.balance) {
      throw new Error('Insufficient funds');
    }
    data.balance -= amount;
  }
}

const account = new BankAccount('Alice', 1000);
console.log('Owner:', account.owner);
console.log('Balance (via method):', account.getBalance());
console.log('Balance (direct access):', account.balance); // undefined!
account.deposit(500);
console.log('After deposit:', account.getBalance());

// ============================================
// WEAKSET EXAMPLES
// ============================================

console.log('\n=== WeakSet Examples ===');

const weakSet = new WeakSet();

const obj1 = { type: 'object1' };
const obj2 = { type: 'object2' };

weakSet.add(obj1);
weakSet.add(obj2);

console.log('Has obj1:', weakSet.has(obj1));
console.log('Has obj2:', weakSet.has(obj2));

// Use case: Track processed items
const processed = new WeakSet();

function processItem(item) {
  if (processed.has(item)) {
    console.log('Item already processed, skipping');
    return;
  }

  processed.add(item);
  console.log('Processing item:', item.id);
  // ... process item
}

const item1 = { id: 1, data: 'first' };
const item2 = { id: 2, data: 'second' };

processItem(item1); // Processes
processItem(item1); // Skips (already processed)
processItem(item2); // Processes

// ============================================
// PRACTICAL EXAMPLES
// ============================================

console.log('\n=== Practical Examples ===');

// Example 1: Counting occurrences with Map
function countOccurrences(arr) {
  const counts = new Map();
  for (const item of arr) {
    counts.set(item, (counts.get(item) || 0) + 1);
  }
  return counts;
}

const fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple'];
const fruitCounts = countOccurrences(fruits);
console.log('Fruit counts:', Object.fromEntries(fruitCounts));

// Example 2: Caching with Map
const cache = new Map();

function fibonacci(n) {
  if (cache.has(n)) {
    return cache.get(n);
  }

  const result = n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2);
  cache.set(n, result);
  return result;
}

console.log('Fibonacci(40):', fibonacci(40));
console.log('Cache size:', cache.size);

// Example 3: Set for tags/categories
class Article {
  constructor(title) {
    this.title = title;
    this.tags = new Set();
  }

  addTag(tag) {
    this.tags.add(tag.toLowerCase());
    return this;
  }

  removeTag(tag) {
    this.tags.delete(tag.toLowerCase());
    return this;
  }

  hasTag(tag) {
    return this.tags.has(tag.toLowerCase());
  }

  getTags() {
    return [...this.tags];
  }
}

const article = new Article('JavaScript Collections');
article
  .addTag('JavaScript')
  .addTag('ES6')
  .addTag('Tutorial')
  .addTag('javascript'); // Duplicate (case-insensitive)

console.log('Article tags:', article.getTags());
console.log('Has JavaScript tag:', article.hasTag('JAVASCRIPT'));

// Example 4: Graph representation with Map
class Graph {
  constructor() {
    this.adjacencyList = new Map();
  }

  addVertex(vertex) {
    if (!this.adjacencyList.has(vertex)) {
      this.adjacencyList.set(vertex, new Set());
    }
  }

  addEdge(v1, v2) {
    this.addVertex(v1);
    this.addVertex(v2);
    this.adjacencyList.get(v1).add(v2);
    this.adjacencyList.get(v2).add(v1); // Undirected
  }

  getNeighbors(vertex) {
    return [...(this.adjacencyList.get(vertex) || [])];
  }
}

const graph = new Graph();
graph.addEdge('A', 'B');
graph.addEdge('A', 'C');
graph.addEdge('B', 'D');

console.log('Neighbors of A:', graph.getNeighbors('A'));
console.log('Neighbors of B:', graph.getNeighbors('B'));

console.log('\n=== Examples Complete ===');
Examples - JavaScript Tutorial | DeepML