I have an array of objects, where each object has a unique member called id
. How do I create a Map where the id
if the Map's key?
Asked
Active
Viewed 1.1k times
6
-
Could you explain a bit more, do you have an example array?.. And what output you expect. – Keith Oct 24 '16 at 13:58
-
JSPrefs for the 3 answers below are here: https://jsperf.com/array-to-map-4 – Ross Oct 24 '16 at 15:06
-
Should be pretty simple. Have you tried it yourself? Please show us your code. What did not work? – Bergi Oct 24 '16 at 15:24
3 Answers
8
You want to reduce your array into a map:
const arr = [{id:1},{id:2},{id:2}];
const map = arr.reduce((acc, item) => acc.set(item.id, item), new Map());
console.log(map.get(1));
Here is a JSPref against using map
and forEach
.
In Chrome v53 reduce
is fastest, then forEach
with map
being the slowest.

Ross
- 14,266
- 12
- 60
- 91
-
Curious to know why this got a down vote. It's not making intermediate arrays which may not be faster (and will bump the garbage collector later) – Ross Oct 24 '16 at 14:21
-
-
I'd say for someone reading the code, this is more literate of its intension. Therefore simpler. Unless you don't know what `reduce` is of course. – Ross Oct 24 '16 at 14:29
-
Harsh downvote. It may look complex on the surface, but this is simply a pure function with no side-effects and so is easier to reason about. – CodingIntrigue Oct 24 '16 at 14:33
-
-
1@Gothdo I've changed it to `const`. (It appears you didn't get the irony) – Ross Oct 24 '16 at 14:47
-
@Gothdo I've added a JSPref for my own curiosity. For me this runs 48% faster than using `map` – Ross Oct 24 '16 at 14:57
-
-
Nice. Tbh very little difference on chrome between forEach and reduce on Chrome. It's allocating the arrays rather than called set which is a performance hit. – Ross Oct 24 '16 at 18:56
3
You could map a new array in the needed format for the Map.
var array = [{ id: 1, value: 'one' }, { id: 2, value: 'two' }, { id: 3, value: 'three' }, { id: 4, value: 'four' }, { id: 5, value: 'five' }],
map = new Map(array.map(a => [a.id, a]));
console.log([...map]);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Or iterate and add the new item to a certain key
var array = [{ id: 1, value: 'one' }, { id: 2, value: 'two' }, { id: 3, value: 'three' }, { id: 4, value: 'four' }, { id: 5, value: 'five' }],
map = new Map();
array.forEach(a => map.set(a.id, a));
console.log([...map]);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Nina Scholz
- 376,160
- 25
- 347
- 392
-
1In ES6 it's better to use for..of loop instead of `forEach()` method, see [Are there reasons to use array.forEach() over for…of, when both could be used, in ES6?](http://stackoverflow.com/q/31344516/3853934). `forEach()` is also slower than a loop. – Michał Perłakowski Oct 24 '16 at 14:21
-
-
But you don't know if someone using this code won't need to modify it to exit the loop. And still it's slower. – Michał Perłakowski Oct 24 '16 at 14:29
-
1@Gothdo Can't see how `for..of` provides any benefits over `forEach` here. In fact, using `forEach` allows for abstraction into a smaller, reusable method, e.g. `const addToMap = item => map.set(item.id, item); array.forEach(addToMap);` – CodingIntrigue Oct 24 '16 at 14:29
-
1@CodingIntrigue If you want to use functional programming with composable methods, you shouldn't use side effects like `set`. So that's hardly an advantage here. At least, use `reduce` instead of `forEach` like in Ross' answer. And really, for imperative iteration (which is what we need here) `for…of` loops are more idiomatic ES6. – Bergi Oct 24 '16 at 15:26
-
@Bergi Not arguing that a pure function isn't a better choice. Just given this answer there is more benefit to forEach. Being idiomatic ES6 is subjective at best. Abstraction is quantifiable, rightly or wrongly used. – CodingIntrigue Oct 24 '16 at 16:40
3
You can use Array.prototype.map()
to map the array elements to [element.id, element]
pairs and then pass the resulting array to the Map
constructor.
const arr = [{id: 1, a: true, b: false}, {id: 2, a: false, b: true}]
const map = new Map(arr.map(element => [element.id, element]))
// Check if map looks OK
for (const [key, value] of map) {
console.log(key, value)
}

Michał Perłakowski
- 88,409
- 26
- 156
- 177