JavaScript Map, Set, and Grouping Methods
Learn Map, Set, Object.groupBy, and Map.groupBy with examples for keyed collections, unique values, set operations, and grouped data.
JavaScript Map, Set, and Grouping Methods
Map, Set, Object.groupBy(), and Map.groupBy() solve different collection and data-shaping problems. Use Map for keyed values with any key type,
Set for unique values and set operations, and grouping methods when a flat list needs to become lookup-friendly objects.
Map
The Map
object holds key-value pairs and remembers the original insertion order of the keys.
Keys can be any value, including objects, functions, and NaN. Unlike objects, maps offer consistent
key ordering and a cleaner API for frequent additions and deletions.
Instance methods:
Map.prototype.clear()Map.prototype.delete()Map.prototype.entries()Map.prototype.forEach()Map.prototype.get()Map.prototype.has()Map.prototype.keys()Map.prototype.set()Map.prototype.values()
Instance properties:
Map.prototype.size
const map = new Map();
map.set("name", "Alice");
map.set("age", 25);
map.set("country", "USA");
console.log(map);
// Map(3) { 'name' => 'Alice', 'age' => 25, 'country' => 'USA' }
// Size
console.log(map.size); // 3
// Accessing values
console.log(map.get("name")); // Alice
// Checking for a key
console.log(map.has("age")); // true
// Removing a key
map.delete("country");
console.log(map);
// Map(2) { 'name' => 'Alice', 'age' => 25 }
map.set("city", "New York");
map.set("hobby", "Painting");
// Using for...of
console.log("Using for...of:");
for (const [key, value] of map) {
console.log(key, ":", value);
}
// Getting all keys, values, or entries
console.log("Keys:", [...map.keys()]);
// Keys: [ 'name', 'age', 'city', 'hobby' ]
console.log("Values:", [...map.values()]);
// Values: [ 'Alice', 25, 'New York', 'Painting' ]
console.log("Entries:", [...map.entries()]);
// Entries: [
// [ 'name', 'Alice' ],
// [ 'age', 25 ],
// [ 'city', 'New York' ],
// [ 'hobby', 'Painting' ]
// ]
// Clearing the map
map.clear();
console.log(map); // Map(0) {}
// Creating a Map with an array of entries
const mapFromArray = new Map([
["fruit", "Apple"],
["color", "Red"],
["quantity", 10],
]);
console.log(mapFromArray);
// Map(3) { 'fruit' => 'Apple', 'color' => 'Red', 'quantity' => 10 }
// Converting a Map back to an object
const obj = Object.fromEntries(mapFromArray);
console.log(obj);
// { fruit: 'Apple', color: 'Red', quantity: 10 }
// Map vs Object comparison
const objExample = { a: 1, b: 2, c: 3 };
const mapExample = new Map(Object.entries(objExample));
console.log(mapExample);
// Map(3) { 'a' => 1, 'b' => 2, 'c' => 3 }
// Keys of different types
const map2 = new Map();
const keyObj = {};
const keyFunc = function () {};
map2.set("hello", "string value");
map2.set(keyObj, "obj value");
map2.set(keyFunc, "func value");
map2.set(NaN, "NaN value");
console.log(map2);
// Map(4) {
// 'hello' => 'string value',
// {} => 'obj value',
// [Function: keyFunc] => 'func value',
// NaN => 'NaN value'
// }
console.log(map2.get("hello")); // string value
console.log(map2.get(keyObj)); // obj value
console.log(map2.get(keyFunc)); // func value
console.log(map2.get(NaN)); // NaN valueSet
The Set object lets you store unique values of any type, whether primitive or object references.
A Set automatically removes duplicate elements and maintains the insertion order.
The example creates a set, checks membership, removes values, iterates in insertion order, and implements union, intersection, and difference.
// Create a Set
const mySet = new Set([1, 2, 3, 4, 5]);
console.log(mySet); // Set { 1, 2, 3, 4, 5 }
// returns a new set iterator object that contains the values
// for each element in this set in insertion order
const setValues = mySet.values();
console.log(setValues);
// [Set Iterator] { 1, 2, 3, 4, 5 }
console.log(setValues.next()); // { value: 1, done: false }
// Add elements to a Set
mySet.add(6); // Adds a new element
mySet.add(2); // Duplicate values are ignored
console.log(mySet); // Set { 1, 2, 3, 4, 5, 6 }
// Check if a Set contains an element
console.log(mySet.has(3)); // true
console.log(mySet.has(10)); // false
// Remove elements from a Set
mySet.delete(4); // Removes the element 4
console.log(mySet); // Set { 1, 2, 3, 5, 6 }
// Get the size of a Set
console.log(mySet.size); // 5
// Iterate over a Set
for (const value of mySet) {
console.log(value); // Logs each value in the Set
}
// Convert a Set to an Array
const arrayFromSet = Array.from(mySet); // Using Array.from()
console.log(arrayFromSet); // [1, 2, 3, 5, 6]
const anotherArray = [...mySet]; // Using spread operator
console.log(anotherArray); // [1, 2, 3, 5, 6]
// Clear a Set
mySet.clear(); // Removes all elements
console.log(mySet); // Set {}
// Find the Union of Two Sets
const setA = new Set([1, 2, 3]);
const setB = new Set([3, 4, 5]);
// Combines elements from both sets
const union = new Set([...setA, ...setB]);
console.log(union); // Set { 1, 2, 3, 4, 5 }
// Find the Intersection of Two Sets
// Common elements
const intersection = new Set([...setA].filter((x) => setB.has(x)));
console.log(intersection); // Set { 3 }
// Find the Difference of Two Sets
// Elements in setA not in setB
const difference = new Set([...setA].filter((x) => !setB.has(x)));
console.log(difference); // Set { 1, 2 }
const a = {};
const b = {};
const c = {};
const setOfObjects = new Set([a, a, b]);
console.log(setOfObjects); // Set(2) { {}, {} }
console.log(setOfObjects.has(a)); // true
console.log(setOfObjects.has(c)); // falseObject.groupBy
The Object.groupBy()
static method groups elements of an iterable based on the string key returned by a callback function.
It returns a plain object with keys representing group names and values as arrays of grouped items.
The manual implementation uses reduce() to group inventory items by their type field.
const groupBy = (arr, callback) => {
return arr.reduce((acc = {}, item) => {
const key = callback(item);
if (!acc[key]) acc[key] = [];
acc[key].push(item);
return acc;
}, {});
};
const inventory = [
{ name: "asparagus", type: "vegetables", quantity: 5 },
{ name: "bananas", type: "fruit", quantity: 0 },
{ name: "goat", type: "meat", quantity: 23 },
{ name: "cherries", type: "fruit", quantity: 5 },
{ name: "fish", type: "meat", quantity: 22 },
];
const result = groupBy(inventory, ({ type }) => type);
console.log(result);
// {
// vegetables: [{ name: "asparagus", type: "vegetables", quantity: 5 }],
// fruit: [
// { name: "bananas", type: "fruit", quantity: 0 },
// { name: "cherries", type: "fruit", quantity: 5 },
// ],
// meat: [
// { name: "goat", type: "meat", quantity: 23 },
// { name: "fish", type: "meat", quantity: 22 },
// ],
// };Map.groupBy
The Map.groupBy()
static method groups elements from an iterable based on the return value of a callback function.
It returns a new Map where each key is the grouping criterion and each value is an array of items in that group.
// Map.groupBy isn't available yet
function groupBy(array, callback) {
const map = new Map();
for (const item of array) {
const key = callback(item);
const group = map.get(key) || [];
group.push(item);
map.set(key, group);
}
return map;
}
// Using Map.groupBy to group numbers by even and odd
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const groupedNumbers = groupBy(numbers, (num) =>
num % 2 === 0 ? "even" : "odd",
);
console.log(groupedNumbers);
// Map(2) {
// 'odd' => [1, 3, 5, 7, 9],
// 'even' => [2, 4, 6, 8]
// }
// Grouping people by their age group
const people = [
{ name: "Alice", age: 25 },
{ name: "Bob", age: 30 },
{ name: "Charlie", age: 25 },
{ name: "David", age: 35 },
];
const groupedByAge = groupBy(people, (person) => person.age);
console.log(groupedByAge);
// Map(3) {
// 25 => [ { name: 'Alice', age: 25 }, { name: 'Charlie', age: 25 } ],
// 30 => [ { name: 'Bob', age: 30 } ],
// 35 => [ { name: 'David', age: 35 } ]
// }
const inventory = [
{ name: "asparagus", type: "vegetables", quantity: 9 },
{ name: "bananas", type: "fruit", quantity: 5 },
{ name: "goat", type: "meat", quantity: 23 },
{ name: "cherries", type: "fruit", quantity: 12 },
{ name: "fish", type: "meat", quantity: 22 },
];
// Using objects as keys
const restock = { restock: true };
const sufficient = { restock: false };
const result = groupBy(inventory, ({ quantity }) =>
quantity < 6 ? restock : sufficient,
);
console.log(result);
// Map(2) {
// { restock: false } => [
// { name: 'asparagus', type: 'vegetables', quantity: 9 },
// { name: 'goat', type: 'meat', quantity: 23 },
// { name: 'cherries', type: 'fruit', quantity: 12 },
// { name: 'fish', type: 'meat', quantity: 22 }
// ],
// { restock: true } => [ { name: 'bananas', type: 'fruit', quantity: 5 } ]
// }
console.log(result.get(restock));
// [{ name: "bananas", type: "fruit", quantity: 5 }]