Looking for comparisons? Refer to the articles below:
- ES6 — Map vs Object — What and when?
- ES6 — Set vs Array — What and when?
- JavaScript Collections – Set and Map
Map
Creating an instance
1) Using the constructor:
const colors = new Map();
2) Passing an iterable:
const colors = new Map([
["#ff0000", "red"],
["#0000ff", "blue"]
]);
// => colors: {"#ff0000" => "red", "#0000ff" => "blue"}
3) Using the set()
method which is chainable:
const colors = new Map()
.set("#ff0000", "red")
.set("#0000ff", "blue");
// => colors: {"#ff0000" => "red", "#0000ff" => "blue"}
Methods
1) Reading and writing:
const colors = new Map([
["#ff0000", "red"]
]);
colors.get("#ff0000");
// => "red"
colors.get("#0000ff");
// => undefined
Writing has already been covered, though, but for the sake of completeness:
const colors = new Map();
colors.set("#0000ff", "blue");
// colors: {"#0000ff" => "blue"}
2) Checking if the entry with the given key exists:
const colors = new Map().set("#ff0000", "red");
colors.has("#ff0000");
// => true
3) Getting the keys and values:
const colors = new Map().set("#ff0000", "red");
for (const hex of colors.keys()) {
console.log(hex);
}
// => "#ff0000"
for (const color of colors.values()) {
console.log(color);
}
// => "red"
for (const [hex, color] of colors.entries()) {
console.log(hex, "=>", color);
}
// => "#ff0000 => red"
4) Removing a single entry:
The delete()
method returns a boolean according to the operation's result.
const colors = new Map().set("#ff0000", "red");
colors.delete("#ff0000");
// => true
colors.delete("foo");
// => false
5) Removing all entries:
const colors = new Map().set("#ff0000", "red");
colors.clear();
// => colors: {}
Properties
When it comes to retrieving the size of a map (that is, the number of entries it has), it's more convenient than that of an object:
const colors = new Map([
["#ff0000", "red"]
]);
console.log(colors.size);
// => 1
colors.set("#0000ff", "blue");
console.log(colors.size);
// => 2
Tips & Tricks
1) Converting between Maps and Objects
The conversion is possible so long as the map consists of keys of types of strings and symbols.
const colors = new Map([
["#ff0000", "red"]
]);
const obj = Object.fromEntries(colors);
// => obj: {"#ff0000": "red"}
2) Mapping and filtering
Steps:
const numbers = new Map([
[1, "a"],
[2, "b"],
[3, "c"]
]);
const mappedNumbers = new Map( // 3
[...numbers] // 1
.map( // 2
([number, char]) => [number * 10, char]
)
);
// => mappedNumbers: {10 => "a", 20 => "b", 30 => "c"}
const numbers = new Map([
[1, "a"],
[2, "b"],
[3, "c"]
]);
const filteredNumbers = new Map( // 3
[...numbers] // 1
.filter( // 2
([number]) => number > 2
)
);
// => filteredNumbers: {3 => "c"}
3) Key equality is based on sameValueZero
NaN
keys are considered to be equal:
const map = new Map();
map.set(NaN, "foo");
map.get(NaN);
// => "foo"
map.set(NaN, "bar");
map.get(NaN);
// => "bar"
But object keys are always different:
const map = new Map().set({}, "foo").set({}, "bar");
console.log(map.size);
// => 2
Set
Creating an instance
1) Using the constructor:
const set = new Set();
2) Passing an iterable:
const numbers = new Set([1, 2, 3]);
// => numbers: {1, 2, 3}
const chars = new Set("123");
// => chars: {"1", "2", "3"}
3) Using the add()
method which, similarly to set()
, is chainable:
const numbers = new Set()
.add(1)
.add(2)
.add(3);
// => numbers: {1, 2, 3}
Methods
1) Reading and writing values:
Keep in mind the caveat that there's no random access to an element in a Set
(citing from ES6 — Set vs Array — What and when?):
More important, because the Array data is stored in consecutive memory, the CPU will be able to access the data much faster due to pre-fetching. Hence in general accessing an elements in Array (one after the other such as in a for loop) is quicker and more efficient if you compared to other type of abstract data types.
There are workarounds to locate specific elements though. For instance, to get the first element of a set you can grab an iterator from values()
and then call the next()
method (original solution from StackOverflow):
const numbers = new Set()
.add(1)
.add(2)
.add(3);
const firstElement = numbers.values().next().value;
// => firstElement: 1
2) Checking if an element is a member of the collection:
const numbers = new Set()
.add(1)
.add(2)
.add(3);
numbers.has(1);
// => true
numbers.has(4);
// => false
3) Removing a single element:
Just like the delete()
method of Map
, the returned boolean value indicates if the operation was successful:
const numbers = new Set()
.add(1)
.add(2)
.add(3);
numbers.delete(1);
// => true
numbers.delete(4);
// => false
4) Removing all elements:
const numbers = new Set()
.add(1)
.add(2)
.add(3);
numbers.clear();
// => numbers: {}
Properties
const numbers = new Set()
.add(1)
.add(2)
.add(3);
console.log(numbers.size);
// => 3
Tips & Tricks
1) Removing duplicated elements from an Array:
const arr = [1, 1, 2, 3, 4, 4, 5];
const filteredArr = [...new Set(arr)];
// => filteredArr: [1, 2, 3, 4, 5]
2) Iteration:
const numbers = new Set()
.add(1)
.add(2)
.add(3);
for (const number of numbers) {
console.log(number);
}
// => 1
// => 2
// => 3
3) As with Map
keys, NaN
elements are considered to be equal:
const nanSet = new Set([NaN, NaN, NaN, NaN]);
console.log(nanSet.size);
// => 1
But objects are always different:
const objSet = new Set([{}, {}, {}]);
console.log(objSet.size);
// => 3
4) Mapping and filtering
const numbers = new Set()
.add(1)
.add(2)
.add(3);
const mappedNumbers = new Set([...numbers].map(number => number * 2));
// => mappedNumbers: {2, 4, 6}
const numbers = new Set()
.add(1)
.add(2)
.add(3);
const filteredNumbers = new Set([...numbers].filter(number => number > 2));
// => filteredNumbers: {3}
5) Union
const a = new Set(["foo", "bar"]);
const b = new Set(["foo", "buzz"]);
const union = new Set([...a, ...b]);
// => union: {"foo", "bar", "buzz"}
6) Intersection
const a = new Set(["foo", "bar"]);
const b = new Set(["foo", "buzz"]);
const intersection = new Set([...a].filter(val => b.has(val)));
// => intersection: {"foo"}
7) Difference
const a = new Set(["foo", "bar"]);
const b = new Set(["foo", "buzz"]);
const difference = new Set([...a].filter(val => !b.has(val)));
// => difference: {"bar"}
I hope you found the article helpful! Until next time!
Psst. Would you like to add something? I'd like to hear about it. Just leave a comment or drop me a message on Twitter.
Top comments (0)