How to convert an array of objects to directories alike.
Tags: javascript
Published: 2023-07-23 13:40:57


---
title: How to convert an array of objects to directories alike.
published: true
tags: Javascript
canonical_url: https://blog.melvinvmegen.com/snippets/array-directories
---

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mgvitlpvtgkxfl832b7p.png)

## Context

As javascript developers, we are constantly manipulating arrays of objects. And more often than not we want the data to be easily retrievable or simply well structured, like a directory would be. Now, suppose you have an array of objects representing books, and you want to quickly create an object where the keys are book titles and the values are the corresponding book objects. You can use the **keyBy** function to achieve this in a single line of code!

## Usage

The **keyBy** function takes two arguments, an **array** and a **key string** (which could be made optional and default to the id property or whatever suits your use cases the most). 
The [reduce](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) method is then used to iterate over each element of the provided array, creating a new object where the keys are based on the values of the **parameter key** in each object and the object itself as the value.

Let's make this more concrete with our books example:

```js
// Primitives values
let books = [
  "The Great Gatsby",
  "To Kill a Mockingbird",
  "Pride and Prejudice",
];
let booksByKey = keyBy(books);
// {
//    "The Great Gatsby": "The Great Gatsby",
//    "To Kill a Mockingbird": "To Kill a Mockingbird",
//    "Pride and Prejudice": "Pride and Prejudice"
// }

// Object values
books = [
  { title: "The Great Gatsby", author: "F. Scott Fitzgerald", year: 1925 },
  { title: "To Kill a Mockingbird", author: "Harper Lee", year: 1960 },
  { title: "Pride and Prejudice", author: "Jane Austen", year: 1813 },
];
booksByKey = keyBy(books, "title");
// {
// 'The Great Gatsby': { title: 'The Great Gatsby', author: 'F. Scott Fitzgerald', year: 1925 },
// 'To Kill a Mockingbird': { title: 'To Kill a Mockingbird', author: 'Harper Lee', year: 1960 },
// 'Pride and Prejudice': { title: 'Pride and Prejudice', author: 'Jane Austen', year: 1813 }
// }

// And tada 🎉
booksByKey["The Great Gatsby"].author; // "F. Scott Fitzgerald"
```

This function doesn't handle the case where there are duplicated values, so it would just take the last encountered object for a certain value.

```js
books = [
  { title: "The Great Gatsby", author: "F. Scott Fitzgerald", year: 1925 },
  { title: "To Kill a Mockingbird", author: "Harper Lee", year: 1960 },
  { title: "Pride and Prejudice", author: "Jane Austen", year: 1960 },
];
booksByKey = keyBy(books, "year");
// {
// 'The Great Gatsby': { title: 'The Great Gatsby', author: 'F. Scott Fitzgerald', year: 1925 },
// 'Pride and Prejudice': { title: 'Pride and Prejudice', author: 'Jane Austen', year: 1960 }
// }
```

**Extension**
Let's not stop here, we could easily extend our function to also handle objects of objects :

```js
function collectionKeyBy(collection = {}, key) {
  return Array.isArray(collection)
    ? keyBy(collection, key)
    : keyBy(Object.values(collection), key);
}
```

The **collectionKeyBy** function builds upon the **keyBy** handling the case for both arrays and objects. It takes a collection as a first argument and a **key string** as the second argument, it then checks if the provided **collection** is an **array** using the [isArray](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray) method. If it is, it calls the **keyBy** function directly, if not it will convert our collection to an array thanks to the [Object.values](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/values]) method before calling the still great **keyBy** function. This code can be usefull if you wanna unwrap objects that are keyed randomly by an API, let say you get our books from an endpoint:

```js
const books = {
  book1: {title: 'The Great Gatsby', author: 'F. Scott Fitzgerald', year: 1925},
  book2: {title: 'To Kill a Mockingbird', author: 'Harper Lee', year: 1960},
  book3: {title: 'Pride and Prejudice', author: 'Jane Austen', year: 1813}
}
collectionKeyBy(books, "name");
// {
//   "The Great Gatsby": {
//       "title": "The Great Gatsby",
//       "author": "F. Scott Fitzgerald",
//       "year": 1925
//   },
//   "To Kill a Mockingbird": {
//       "title": "To Kill a Mockingbird",
//       "author": "Harper Lee",
//       "year": 1960
//   },
//   "Pride and Prejudice": {
//       "title": "Pride and Prejudice",
//       "author": "Jane Austen",
//       "year": 1960
//   }
// }
```

## Conclusion:

The **keyBy** supercharged by the **collectionKeyBy** function are useful utility functions that can be used to generate a key based directory from an array or an object of objects with flexibility and ease in mind. Happy coding!