How to convert an Array to a Map in JavaScript


In this blogpost, we will see ways to convert an Array of Objects to a Map in JavaScript. We’ll also explore Nesting, Lazy-evaluation using Proxy, convert back from Map to Array, and a practice question to cement the concepts.

Lets dive in, and make you JavaScript Data Structure Alchemist 🧙‍♂️!


Refresher: Arrays and Maps in JavaScript:

  • Arrays: Arrays in JavaScript are special objects used to store ordered collections. They’re like lists where each item has a numeric index. Key methods:
    • .push() adds items to the end.
    • .pop() removes the last item.
    • .map() creates a new array with the results of calling a function for every array element.
    • .filter() creates a new array with all elements that pass a test implemented by the provided function.
    • .reduce() executes a reducer function on each element, resulting in a single output value.
  • Map: A Map in JavaScript holds key-value pairs where keys can be any data type. It remembers the original insertion order of the keys.
    • .set() adds or updates elements.
    • .get() retrieves a specific element.
    • .has() checks if a key exists.
    • .delete() removes an element.
Basic looping on JavaScript Object (JavaScript)
// Array Methods:

//   Construction and pushin elements
let fruits = ['Apple', 'Banana']; // Construction
fruits.push('Cherry'); // Pushing elements
console.log(fruits); // Output: ['Apple', 'Banana', 'Cherry']

//   Popping Array elements:
fruits.pop();
console.log(fruits); // Output: ['Apple', 'Banana']

//   Map elements from one to another array using a function
const numbers = [1, 2, 3];
const doubled = numbers.map(num => num * 2);
console.log(doubled); // Output: [2, 4, 6]

//   Filter elements passing a test.
const filtered = numbers.filter(num => num > 1);
console.log(filtered); // Output: [2, 3]

// Reduce the array to a single value:
const sum = numbers.reduce(
    (accumulator, currentValue) => accumulator + currentValue, 0);
console.log(sum); // Output: 6

// - - - - - - - - 

// Map Methods:

//   set() method to assign/modify key/value pairs
let colorMap = new Map();
colorMap.set('Apple', 'Red');
colorMap.set('Banana', 'Yellow');
console.log(colorMap); // Output: Map(2) {'Apple' => 'Red', 'Banana' => 'Yellow'}

//   get() to retrieve specific element:
console.log(colorMap.get('Apple')); // Output: 'Red'

//   .has(): Checks if a key exists in the Map.
console.log(colorMap.has('Banana')); // Output: true

//   .delete(): Removes a specified element.
colorMap.delete('Banana');
console.log(colorMap.has('Banana')); // Output: false

//   Constructor using 2 dimensional Array (of key -value).
let anotherMap = new Map([['Orange', 'Orange'], ['Grape', 'Purple']]);
console.log(anotherMap.get('Grape')); // Output: 'Purple'

Applications of Array to Map Conversion in JavaScript

  • Data Manipulation in Web Development:
    • Converting arrays to Maps can simplify state management in React or Vue.js.
    • Accessing and storing data using Map key is more convenient than simply storing in array.
  • Cache Implementation:
    • Maps created from arrays can serve as an effective caching mechanism.
    • They allow for quick retrieval of data based on keys, which is much more efficient than iterating over an array for each lookup.

Ways to convert Array to Map in JavaScript

Using Array.map() and Map() Constructor

This method involves mapping each array element (which could be an object) to a key-value pair array, and then using these pairs to construct a Map. Particularly useful when dealing with data that is naturally structured as key-value pairs but is initially represented in an array format. Let see this in action.

Object.keys() u0026 reverse() (JavaScript)
const arrayOfObjects = [
  { key: 'name', value: 'Alice' },
  { key: 'age', value: 30 }
];

// Using Array.map() to transform the 
// array of objects into an array of [key, value] pairs
const keyValuePairs = arrayOfObjects.map(obj => [obj.key, obj.value]);
console.log(keyValuePairs);
// Output: [ [ 'name', 'Alice' ], [ 'age', 30 ] ]

// Creating a new Map from the 
// 2 dimensional key-value pair array
const mapFromObjects = new Map(keyValuePairs);

console.log(mapFromObjects.get('name')); // Output: Alice
console.log(mapFromObjects.get('age'));  // Output: 30
  • Array Mapping: The arrayOfObjects.map() function iterates over each object in the array. For each object, it returns an array consisting of two elements: the value of obj.key and obj.value.
  • Map Construction: The Map() constructor takes the array of key-value pair arrays and constructs a new Map. Each key-value pair array turns into an entry in the Map.
  • Accessing Map Values: Using mapFromObjects.get('name') and mapFromObjects.get('age'), we can access the values associated with each key in the newly created Map.

Using forEach() with Object.keys() and reverse()

This method is an iterative approach to construct a Map from an array. Uses multiple set calls on Map to add key-value pairs. Can also be used to do checks before adding to Map.

Spread, Object.keys() u0026 reverse() (JavaScript)
const arrayData = [
  { key: 'location', value: 'New York' },
  { key: 'temperature', value: '22°C' }
];

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

// Iterating over the array and adding items to the Map
arrayData.forEach(item => {
  // You can add additional logic here if needed
  mapUsingForEach.set(item.key, item.value);
});

console.log(mapUsingForEach.get('location')); // Output: New York
console.log(mapUsingForEach.get('temperature')); // Output: 22°C
  • Creating an Empty Map: We start by creating an empty Map using new Map().
  • Iterating with forEach(): The arrayData.forEach() method is used to iterate through each element in the array.
  • Adding to the Map: Inside the forEach loop, we use the Map.set() method to add each key-value pair to the Map.
  • Retrieving Values: We can retrieve values from the Map using the Map.get() method.

Using reduce()

The reduce() method is a more functional programming approach, accumulating array elements into a single Map.

Object.values() u0026 reverse() (JavaScript)
const keyValueArray = [['ID', 123], ['status', 'active']];

// Using reduce() to build the Map
const mapFromReduce = keyValueArray.reduce((map, [key, value]) => {
  return map.set(key, value);
}, new Map());

console.log(mapFromReduce.get('ID'));     // Output: 123
console.log(mapFromReduce.get('status')); // Output: active
  • Starting with reduce(): The reduce() method takes two parameters: a reducer function and an initial value (here, a new Map).
  • Reducer Function: Inside the reducer, we add each key-value pair to the accumulator (map), which is initially an empty Map.
  • Building the Map: The map.set(key, value) adds each key-value pair to the Map, and then the Map is returned for the next iteration.

Direct Conversion from Two-Dimensional Arrays

A straightforward method when dealing with two-dimensional arrays, where each element is a key-value pair.

Object.entries() u0026 reverse() (JavaScript)
const twoDimArray = [['fruit', 'apple'], ['color', 'red']];

// Directly converting the 2D array to a Map
const mapFrom2DArray = new Map(twoDimArray);

console.log(mapFrom2DArray.get('fruit')); // Output: apple
console.log(mapFrom2DArray.get('color')); // Output: red
  • Array Structure: The array twoDimArray is an array of arrays, with each inner array representing a key-value pair.
  • Using the Map() Constructor: The Map() constructor can directly take this array of arrays and convert it into a Map.

Tips on converting Array to Map in Javascript

Convert Complex (Nested) Array to Map in JavaScript

To convert arrays with mixed data types, like (nested with arrays, objects, Sets, Maps, Dates, Strings, Numbers, and Symbols) into Maps, we need custom function. Essentially, this function should identify each element type and process it accordingly to form key-value pairs suitable for a Map.

Such functions always depends upon the project needs, but one such implementation is below. You can extend with more if-else clauses if needed.

ES6 Object Property Ordering (JavaScript)
function convertComplexArrayToMap(arr) {
  const complexMap = new Map();
  let tempKey = null;

  arr.forEach(item => {
    if (Array.isArray(item)) {
      // Array: treat as key-value pair
      complexMap.set(item[0], item[1]);
    } else if (item instanceof Map) {
      // Map: add each entry to the complexMap
      item.forEach((value, key) => complexMap.set(key, value));
    } else if (item instanceof Object && !(item instanceof Date) && !(item instanceof Symbol)) {
      // Object (excluding Date and Symbol): add entries to the complexMap
      Object.entries(item).forEach(([key, value]) => complexMap.set(key, value));
    } else {
      // Primitive types or Date/Symbol: handle as key or value
      if (tempKey === null) {
        tempKey = item; // Store as key
      } else {
        complexMap.set(tempKey, item); // Set key-value pair
        tempKey = null; // Reset for next pair
      }
    }
  });

  return complexMap;
}

// Testing the function with a complex array
let complexArray = [
  'key1', 'value1',
  ['nestedArrayKey', ['nested', 'array']],
  'key2', 42,
  { objKey: 'objValue' },
  new Map([['mapKey', 'mapValue']])
];

let complexMap = convertComplexArrayToMap(complexArray);
console.log(complexMap);
// Expected Output: 👎
// Map(5) {
//    "key1" => "value1", 
//    "nestedArrayKey" => ["nested", "array"], 
//    "key2" => 42, 
//    "objKey" => "objValue", 
//    "mapKey" => "mapValue"
// }
  • Iterate Over Array Elements: The function iterates over each item in the array.
  • Handling Different Types:
    • Arrays: Treated as key-value pairs.
    • Maps: Entries added to the new Map.
    • Objects: Object entries (excluding Dates and Symbols) are added.
    • Primitives, Dates, Symbols: Handled as keys or values. A temporary key storage (tempKey) is used for pairing.
  • Constructing the Map: The function accumulates entries in complexMap, resulting in a Map that mirrors the structure and content of the input array.

Lazy Array-to-Map Conversion Using Proxy

Using a JavaScript Proxy for lazy evaluation can enhance performance, particularly with large arrays, by deferring the conversion process until the data is actually accessed.

JavaScript Proxy basics:

Proxy is a layer that sits between your code and the actual object, enabling you to control interactions with that object.

Essentially, its an object that wraps another object (target) and intercepts the operations that are performed on the target object. By using a Proxy, you can define custom behavior for these operations.

Lets see a simple example, where we intercept get-access to the message property on an object.

ES6 Object Property Ordering (JavaScript)
const targetObject = { message: 'Hello, World!' };
const handler = {
  get(target, prop, receiver) {
    if (prop === 'message') {
      return 'Intercepted: ' + target[prop];
    }
    return Reflect.get(target, prop, receiver);
  }
};

const proxyObject = new Proxy(targetObject, handler);

console.log(proxyObject.message); // Output: "Intercepted: Hello, World!"
  • We have a targetObject with a property message.
  • We define a handler object with a get method. This method intercepts the access to any property on targetObject.
  • If the accessed property is message, we modify its value. Otherwise, we return the property’s actual value using Reflect.get.
  • proxyObject is a Proxy for targetObject. When we access proxyObject.message, the get method in the handler is invoked.

Applying Proxy for Lazy Array-to-Map Conversion

Now, let’s apply the concept of a Proxy to perform a lazy conversion of an array to a Map.

ES6 Object Property Ordering (JavaScript)
function lazyArrayToMapProxy(array) {
  const handler = {
    get(target, prop, receiver) {
      if (!target.map) {
        console.log('Converting array to Map...');
        target.map = new Map(array.map(item => [item.id, item]));
      }
      if (typeof target.map[prop] === 'function') {
        return (...args) => target.map[prop](...args);
      }
      return target.map[prop];
    }
  };
  return new Proxy({ map: null }, handler);
}

const usersArray = [{ id: 'user1', name: 'Alice', age: 30 }, { id: 'user2', name: 'Bob', age: 25 }];
const usersMapProxy = lazyArrayToMapProxy(usersArray);

console.log('Accessing user1...');
console.log(usersMapProxy.get('user1')); // Triggers conversion and retrieves user data
console.log('Accessing user2...');
console.log(usersMapProxy.get('user2')); // Directly retrieves user data from the already converted Map

// Output: 👇
//  Accessing user1...
//  Converting array to Map...
//  { id: 'user1', name: 'Alice', age: 30 }
//  Accessing user2...
//  { id: 'user2', name: 'Bob', age: 25 }
  • lazyArrayToMapProxy takes an array and returns a Proxy object. The Proxy intercepts property accesses with a custom get method.
  • Initially, the map property of the target object is null. When a property is accessed for the first time, the get method checks if map is initialized. If not, the array is converted into a Map.
  • The conversion only happens once, at the first access. Subsequent accesses use the already converted Map.
  • This approach is efficient for large datasets where you don’t need to convert the entire dataset upfront.

Reverse: Converting Map to Array in JavaScript

Covered in a lot of detail in this blogpost. But essentially, converting a Map back to an Array involves extracting the Map’s contents in a structured array format. This can be done by obtaining its entries (key-value pairs), just the keys, or just the values. The method chosen depends on what data you need from the Map. We’ll focus on the most comprehensive method: extracting entries.

Using Array.from() to convert Map to Array in JavaScript

Array.from() is a versatile method that creates a new, shallow-copied Array instance from an array-like or iterable object, like a Map. When used with a Map, it converts the Map’s entries into an array.

ES6 Object Property Ordering (JavaScript)
let myMap = new Map([['key1', 'value1'], ['key2', 'value2']]);

// Converting Map to Array using Array.from()
let arrayFromMap = Array.from(myMap);

console.log(arrayFromMap); 
// Output: [['key1', 'value1'], ['key2', 'value2']]
  • Map Initialization: The Map myMap is initialized with two entries: 'key1' mapped to 'value1' and 'key2' mapped to 'value2'.
  • Conversion Process: The Array.from(myMap) call does the conversion. It iterates over the Map’s entries, creating an array where each element is a sub-array representing a key-value pair.
  • Resulting Array Structure: The resulting arrayFromMap is an array of arrays. Each sub-array is an entry from the Map, maintaining the same order as in the Map.
  • Output Explanation: The console log displays the two-dimensional array. Each inner array is one of the Map’s entries, showing how the key-value structure of the Map is preserved in array form.

Using Spread Syntax to convert Map to Array in JavaScript

The spread syntax (...) is another way to convert a Map’s entries into an array. It spreads the entries of the Map into the new array. This method yields the same result as Array.from() but uses a syntax that may be more intuitive for those familiar with ES6 features.

ES6 Object Property Ordering (JavaScript)
let myMap = new Map([['key1', 'value1'], ['key2', 'value2']]);

let spreadArrayFromMap = [...myMap];

console.log(spreadArrayFromMap); 
// Output: [['key1', 'value1'], ['key2', 'value2']]

🧪Practice Coding Problem: Mystical Mapmaker’s Riddle 🧩🧙‍♂️🌍

In the spirit of Test Driven Development ( 😁), lets test our understanding by solving a problem.

As a skilled mapmaker in a mystical realm, you are presented with a magical scroll containing a complex, nested array. This array is a cryptic mix of various elements – arrays, maps, sets, objects, and even primitive types like numbers, strings, dates, and symbols. Your task is to decipher this scroll by converting its contents into a coherent Map, where each unique element finds its rightful place as a key or a value.

Problem (JavaScript)
/**
 * Converts a complex, nested array with mixed types into a Map.
 * @param {Array} mysticalArray - The nested array from the magical scroll.
 * @return {Map} - A Map representing the deciphered contents of the scroll.
 */
function mysticalMapmaker(mysticalArray) {
  // > > > 👉 Write code here 👈 < < <
}

const magicalScroll = [
  ['Crystal Ball', 20],
  ['Potion', new Set(['Healing', 'Invisibility'])],
  [new Map([['Spell', 'Fireball']]), 'Wand'],
  ['Grimoire', { pages: 300 }],
  [Symbol('Magic'), new Date(2023, 0, 1)]
];

console.log(mysticalMapmaker(magicalScroll));
// Expected Output: Map with elements from magicalScroll converted appropriately 👇

//  Map(5) {
//    'Crystal Ball' => 20,
//    'Potion' => Set(2) { 'Healing', 'Invisibility' },
//    Map(1) { 'Spell' => 'Fireball' } => 'Wand',
//    'Grimoire' => { pages: 300 },
//    Symbol(Magic) => 2023-01-01T00:00:00.000Z
//  }
Please attempt before seeing the Answer:
Solution (JavaScript)
function mysticalMapmaker(mysticalArray) {
  const resultMap = new Map();

  mysticalArray.forEach(item => {
    if (Array.isArray(item)) {
      // Array elements are treated as key-value pairs
      resultMap.set(item[0], item[1]);
    } else if (item instanceof Map) {
      // Map elements are spread into the resultMap
      item.forEach((value, key) => resultMap.set(key, value));
    } else if (item instanceof Set) {
      // Sets are stored as values with a unique symbol as the key
      resultMap.set(Symbol('Set'), item);
    } else if (typeof item === 'object') {
      // Objects are stored as values with their constructor name as the key
      resultMap.set(item.constructor.name, item);
    } else {
      // Primitives are stored with a symbol key
      resultMap.set(Symbol('Primitive'), item);
    }
  });

  return resultMap;
}

Explanation:

  • The mysticalMapmaker function processes each element of mysticalArray.
  • For arrays, the first and second elements are treated as key-value pairs.
  • For Map elements, each key-value pair is added to resultMap.
  • Sets are uniquely identified with a symbol key, preserving their uniqueness.
  • Objects are stored with their constructor names as keys to categorize them.
  • Primitives are assigned a symbol key to differentiate them.

Now you have mastered all the spells for JavaScript Array to Map Alchemy. ⛧🧿⚗️🧙‍♂️

Don’t stop chief, keep coding! 🚀👨‍💻

Scroll to Top