Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

Use Case

The use case is to convert an array of objects into a hash map based on string or function provided to evaluate and use as the key in the hash map and value as an object itself. A common case of using this is converting an array of objects into a hash map of objects.

The following is a small snippet in JavaScript to convert an array of objects to a hash map, indexed by the attribute value of object. You can provide a function to evaluate the key of hash map dynamically (run time).

function isFunction(func) {
    return Object.prototype.toString.call(func) === '[object Function]';
 * This function converts an array to hash map
 * @param {String | function} key describes the key to be evaluated in each object to use as key for hashmap
 * @returns Object
 * @Example 
 *      [{id:123, name:'naveen'}, {id:345, name:"kumar"}].toHashMap("id")
 *      Returns :- Object {123: Object, 345: Object}
 *      [{id:123, name:'naveen'}, {id:345, name:"kumar"}].toHashMap(function(obj){return obj.id+1})
 *      Returns :- Object {124: Object, 346: Object}
Array.prototype.toHashMap = function(key) {
    var _hashMap = {}, getKey = isFunction(key)?key: function(_obj){return _obj[key];};
    this.forEach(function (obj){
        _hashMap[getKey(obj)] = obj;
    return _hashMap;

You can find the gist here: Converts Array of Objects to HashMap.

You can use JavaScript Map instead of Object. Check out stackoverflow.com/a/54246603/5042169 – Jun Jan 18, 2019 at 1:31 result = arr.reduce((map, obj) => (map[obj.key] = obj.val, map), {}); For ES6 one-liner fans :D – Teodor Sandu Jan 31, 2018 at 14:44 @Mtz For ES6 one-line fans, mateuscb's response below is much smaller and cleaner: result = new Map(arr.map(obj => [obj.key, obj.val]));. Most importantly, it makes it super clear that a map is being returned. – Ryan Shillington Jun 7, 2018 at 16:31 @RyanShillington we are in an answer's context here, which is Array.prototype.reduce as proposed by jmar777. Map is indeed shorter but it's a different thing. I was keeping in line with the original intent. Remember this is not a forum, you might want to read more about the SO Q/A structure. – Teodor Sandu Jun 8, 2018 at 13:59 This isn't what was asked for, IMHO. The correct result for the array shown would be: { "foo": {key: 'foo', val: 'bar'}, "hello": {key: 'hello', val: 'world'} }. Note that each original element should be kept in its entirety. Or using the Q's data: {"345": {id:345, name:"kumar"}, ...}. FIX: Change code to be map[obj.key] = obj; – ToolmakerSteve Nov 3, 2019 at 19:09 var result = new Map(arr.map(i => [i.key, i.val])); // When using TypeScript, need to specify type: // var result = arr.map((i): [string, string] => [i.key, i.val]) // Unfortunately maps don't stringify well. This is the contents in array form. console.log("Result is: " + JSON.stringify([...result])); // Map {"foo" => "bar", "hello" => "world"}
Also important to note that to get something out of a Map you need to use result.get(keyName) as opposed to just result[keyName] . Also note that any object can be used as the key and not just a string. Simon_Weaver Jan 26, 2018 at 8:57 Another TypeScript version would look like this: var result = new Map(arr.map(i => [i.key, i.val] as [string, string])); which some might find easier to understand. Note as [string, string] type cast added. AlexV Nov 21, 2018 at 22:12 Another typescript version: var result = new Map<string, string>(arr.map(i => [i.key, i.val])); azizj Oct 21, 2019 at 20:22 @AlexV that is a type assertion and should be avoided whenever possible. Instead you can type the Map using new Map<string, string> . Krisztián Balla Feb 6, 2022 at 11:39
const array = [
   {key: 'a', value: 'b', redundant: 'aaa'},
   {key: 'x', value: 'y', redundant: 'zzz'}
const hash = Object.fromEntries(
   array.map(e => [e.key, e.value])
console.log(hash) // {a: b, x: y}
This is more readable than the top answer; however, it will iterate the array twice (once for the map call and once for the Object.fromEntries call). knguyen Aug 7, 2020 at 0:53 @knguyen why does it matter if it iterates twice? Are we even sure it will result in a performance hit? Ben Jones Dec 30, 2022 at 22:56

Using ES6 spread + Object.assign:

array = [{key: 'a', value: 'b', redundant: 'aaa'}, {key: 'x', value: 'y', redundant: 'zzz'}]
const hash = Object.assign({}, ...array.map(s => ({[s.key]: s.value})));
console.log(hash) // {a: b, x: y}
                const hash = Object.assign({}, ...(<{}>array.map(s => ({[s.key]: s.value})))); had to do this change to work with typescript.
– ruwan800
                Sep 27, 2019 at 9:55
const result = arr.reduce(
    (accumulator, target) => ({ ...accumulator, [target.key]: target.val }),

Demonstration of the code snippet on jsFiddle.

I'm exactly here because of this! how spread operator performs agains the regular old way of just assign the new key and return the accumulator? since it's creating a new copy each time, then spread will perform poorly! – AMTourky Jul 24, 2018 at 6:30 now you spread in every iteration. It should be safe to mutate in reducer. ``` const result = arr.reduce( (accumulator, target) => { accumulator[target.key]: target.val; return accumulator }, {}); ``` – MTJ Jan 31, 2020 at 12:58

You can use Array.prototype.reduce() and actual JavaScript Map instead just a JavaScript Object.

let keyValueObjArray = [
  { key: 'key1', val: 'val1' },
  { key: 'key2', val: 'val2' },
  { key: 'key3', val: 'val3' }
let keyValueMap = keyValueObjArray.reduce((mapAccumulator, obj) => {
  // either one of the following syntax works
  // mapAccumulator[obj.key] = obj.val;
  mapAccumulator.set(obj.key, obj.val);
  return mapAccumulator;
}, new Map());
console.log(keyValueMap);
console.log(keyValueMap.size);

What is different between Map And Object?
Previously, before Map was implemented in JavaScript, Object has been used as a Map because of their similar structure.
Depending on your use case, if u need to need to have ordered keys, need to access the size of the map or have frequent addition and removal from the map, a Map is preferable.

Quote from MDN document:
Objects are similar to Maps in that both let you set keys to values, retrieve those values, delete keys, and detect whether something is stored at a key. Because of this (and because there were no built-in alternatives), Objects have been used as Maps historically; however, there are important differences that make using a Map preferable in certain cases:

  • The keys of an Object are Strings and Symbols, whereas they can be any value for a Map, including functions, objects, and any primitive.
  • The keys in Map are ordered while keys added to object are not. Thus, when iterating over it, a Map object returns keys in order of insertion.
  • You can get the size of a Map easily with the size property, while the number of properties in an Object must be determined manually.
  • A Map is an iterable and can thus be directly iterated, whereas iterating over an Object requires obtaining its keys in some fashion and iterating over them.
  • An Object has a prototype, so there are default keys in the map that could collide with your keys if you're not careful. As of ES5 this can be bypassed by using map = Object.create(null), but this is seldom done.
  • A Map may perform better in scenarios involving frequent addition and removal of key pairs.
  • You are missing an arrow. Change (mapAccumulator, obj) {...} for (mapAccumulator, obj) => {...} – mayid Feb 11, 2019 at 0:54

    There are better ways to do this as explained by other posters. But if I want to stick to pure JS and ol' fashioned way then here it is:

    var arr = [
        { key: 'foo', val: 'bar' },
        { key: 'hello', val: 'world' },
        { key: 'hello', val: 'universe' }
    var map = {};
    for (var i = 0; i < arr.length; i++) {
        var key = arr[i].key;
        var value = arr[i].val;
        if (key in map) {
            map[key].push(value);
        } else {
            map[key] = [value];
    console.log(map);
                    is it advised to use reduce method than this method. I feel like using this method. its simple and easy to see everything.
    – Santhosh
                    Nov 24, 2018 at 12:47
                    I love this approach. I think sometimes the simplest code is the best. People are turned off by mutability nowadays, but as long as it's contained, mutability is actually pretty awesome and performant.
    – Luis Aceituno
                    May 2, 2019 at 13:47
                    Thank you for posting the only example with multiple keys that are the same, which is the situation I needed to handle. I also like this because as Anthosh said you can actually see what is going on. My only suggestion for improving this answer would be to show the output
    – SendETHToThisAddress
                    Mar 17, 2021 at 21:14
    

    If you want to convert to the new ES6 Map do this:

    var kvArray = [['key1', 'value1'], ['key2', 'value2']];
    var myMap = new Map(kvArray);
    

    Why should you use this type of Map? Well that is up to you. Take a look at this.

    This is what I'm doing in TypeScript I have a little utils library where I put things like this

    export const arrayToHash = (array: any[], id: string = 'id') => 
             array.reduce((obj, item) =>  (obj[item[id]] = item , obj), {})
    

    usage:

    const hash = arrayToHash([{id:1,data:'data'},{id:2,data:'data'}])
    

    or if you have a identifier other than 'id'

    const hash = arrayToHash([{key:1,data:'data'},{key:2,data:'data'}], 'key')
                    If you want to use an object as a key, you'll have to use Map instead of Object because typescript won't let you use objects as keys
    – Dany Dhondt
                    Feb 12, 2019 at 7:20
    const map = _.fromPairs(items.map(item => [item.key, item.val]));
    // OR: if you want to index the whole item by key:
    // const map = _.fromPairs(items.map(item => [item.key, item]));
    

    The lodash fromPairs function reminds me about zip function in Python

    Link to lodash

    var createMapFromList = function(objectList, property) {
        var objMap = {};
        objectList.forEach(function(obj) {
          objMap[obj[property]] = obj;
        return objMap;
    // objectList - the array  ;  property - property as the key
                    isn't using .map(...) pointless in this example as you don't return anything in it? I would suggest forEach in this case.
    – markcheeky
                    Aug 27, 2017 at 19:40
    

    For me, I prefer not to use any map or reduce and just stick with simple for loop.

    const array = [
       {key: 'a', value: 'b', redundant: 'aaa'},
       {key: 'x', value: 'y', redundant: 'zzz'}
    const hash = {};
    for (const item of array) {
        hash[item.key] = item;
    console.log(hash);
                    I agree with @Yada. Easy to read and straight forward code is much preferable for sanity.
    – King Friday
                    Dec 22, 2021 at 14:17
                    im a new react MERN developer started 2 years ago and im getting drowned in all this reduce, filter, map stuff..... im learning it though, filter is most confusing to me.
    – KingJoeffrey
                    Feb 16, 2022 at 3:44
    

    I would make it more clear in TypeScript in case someone is interested.

    interface Person {
      id: number;
      name: string;
    type Result = Map<number, string>
    const input: Array<Person> = [
        id: 123,
        name: "naveen"
        id: 345,
        name: "kumar"
    const convertedToMap: Result = input.reduce(
      (map: Result, person: Person) => {
        map.set(person.id, person.name);
        return map;
      new Map()
    let fkey = o => o.id; // function changing object to string (key)
    let toHashMap = (a,f) => a.reduce((a,c)=> (a[f(c)]=c,a),{});
    console.log( toHashMap(arr,fkey) );
    // Adding to prototype is NOT recommented:
    // Array.prototype.toHashMap = function(f) { return toHashMap(this,f) };
    // console.log( arr.toHashMap(fkey) );
    * convert neste object array to Map by object field * @param {Array<Object>} array * @param {String} fieldName * @returns {Map} function convertNestObjectArrayToMapByField(array, fieldName){ return new Map(array.map(obj => [obj[fieldName], obj])); /* Example const array = [ { key: 'foo', val: 'bar' }, { key: 'hello', val: 'world' } let map = convertNestObjectArrayToMapByField(array, 'key'); console.log(map); console.log(map.get('foo')); # Console Map(2) { 'foo' => { key: 'foo', val: 'bar' }, 'hello' => { key: 'hello', val: 'world' } { key: 'foo', val: 'bar' }

    Following is small snippet i've created in javascript to convert array of objects to hash map, indexed by attribute value of object. You can provide a function to evaluate the key of hash map dynamically (run time).

    function isFunction(func){
        return Object.prototype.toString.call(func) === '[object Function]';
     * This function converts an array to hash map
     * @param {String | function} key describes the key to be evaluated in each object to use as key for hasmap
     * @returns Object
     * @Example 
     *      [{id:123, name:'naveen'}, {id:345, name:"kumar"}].toHashMap("id")
            Returns :- Object {123: Object, 345: Object}
            [{id:123, name:'naveen'}, {id:345, name:"kumar"}].toHashMap(function(obj){return obj.id+1})
            Returns :- Object {124: Object, 346: Object}
    Array.prototype.toHashMap = function(key){
        var _hashMap = {}, getKey = isFunction(key)?key: function(_obj){return _obj[key];};
        this.forEach(function (obj){
            _hashMap[getKey(obj)] = obj;
        return _hashMap;
    

    You can find the gist here : https://gist.github.com/naveen-ithappu/c7cd5026f6002131c1fa

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.