How to filter an array in array of objects in Javascript?

Learn how to filter an array in array of objects in javascript? with practical examples, diagrams, and best practices. Covers javascript development techniques with visual explanations.

Filtering Arrays within Objects in JavaScript

Hero image for How to filter an array in array of objects in Javascript?

Learn various JavaScript techniques to efficiently filter arrays nested within objects, covering common use cases and best practices.

Working with complex data structures is a common task in JavaScript development. Often, you'll encounter an array of objects, where each object itself contains another array. Filtering these nested arrays based on specific criteria requires a good understanding of array methods and object manipulation. This article will guide you through several effective methods to achieve this, from simple filter and map combinations to more advanced techniques.

Understanding the Problem: Nested Data Structures

Before diving into solutions, let's visualize the type of data structure we're dealing with. Imagine a list of users, where each user object has a name and an array of roles. Our goal might be to find users who have a specific role, or perhaps to return users with only certain roles filtered out from their roles array.

graph TD
    A[Array of User Objects]
    A --> B{User Object 1}
    A --> C{User Object 2}
    B --> B1[name: "Alice"]
    B --> B2[roles: ["admin", "editor"]]
    C --> C1[name: "Bob"]
    C --> C2[roles: ["viewer"]]
    B2 --> B2a["admin"]
    B2 --> B2b["editor"]
    C2 --> C2a["viewer"]
    style A fill:#f9f,stroke:#333,stroke-width:2px
    style B fill:#bbf,stroke:#333,stroke-width:2px
    style C fill:#bbf,stroke:#333,stroke-width:2px

Representation of an array of objects with nested arrays.

Method 1: Filtering Parent Objects Based on Nested Array Content

A common requirement is to filter the top-level array of objects, keeping only those objects whose nested array contains at least one element matching a certain condition. This can be achieved using a combination of filter() and some().

const users = [
  { id: 1, name: 'Alice', roles: ['admin', 'editor'] },
  { id: 2, name: 'Bob', roles: ['viewer'] },
  { id: 3, name: 'Charlie', roles: ['admin'] },
  { id: 4, name: 'David', roles: ['guest'] }
];

// Find users who have the 'admin' role
const admins = users.filter(user => 
  user.roles.some(role => role === 'admin')
);

console.log(admins);
/*
[
  { id: 1, name: 'Alice', roles: ['admin', 'editor'] },
  { id: 3, name: 'Charlie', roles: ['admin'] }
]
*/

Filtering parent objects using filter() and some().

Method 2: Filtering Nested Arrays and Returning Modified Objects

Sometimes, you don't want to filter the parent objects, but rather modify them by filtering their internal arrays. For instance, you might want to return all users, but for each user, only include specific roles in their roles array. This involves using map() to iterate over the parent array and filter() for the nested array.

const users = [
  { id: 1, name: 'Alice', roles: ['admin', 'editor', 'developer'] },
  { id: 2, name: 'Bob', roles: ['viewer', 'editor'] },
  { id: 3, name: 'Charlie', roles: ['admin'] }
];

// Return all users, but only include 'admin' or 'editor' roles for each
const usersWithFilteredRoles = users.map(user => ({
  ...user, // Spread existing user properties
  roles: user.roles.filter(role => role === 'admin' || role === 'editor')
}));

console.log(usersWithFilteredRoles);
/*
[
  { id: 1, name: 'Alice', roles: ['admin', 'editor'] },
  { id: 2, name: 'Bob', roles: ['editor'] },
  { id: 3, name: 'Charlie', roles: ['admin'] }
]
*/

Filtering nested arrays using map() and filter().

Method 3: Combining Both: Filter Parent and Filter Nested Arrays

What if you need to do both? Filter the parent objects based on a condition in their nested array, AND then filter the nested array itself for the remaining objects. This requires a two-step process, often chaining filter() and map().

const users = [
  { id: 1, name: 'Alice', roles: ['admin', 'editor', 'developer'] },
  { id: 2, name: 'Bob', roles: ['viewer', 'editor'] },
  { id: 3, name: 'Charlie', roles: ['admin'] },
  { id: 4, name: 'David', roles: ['guest'] }
];

// 1. Filter users who have 'admin' role
// 2. For those users, only keep 'admin' or 'editor' roles
const filteredAndModifiedUsers = users
  .filter(user => user.roles.some(role => role === 'admin')) // Step 1: Filter parent
  .map(user => ({
    ...user,
    roles: user.roles.filter(role => role === 'admin' || role === 'editor') // Step 2: Filter nested
  }));

console.log(filteredAndModifiedUsers);
/*
[
  { id: 1, name: 'Alice', roles: ['admin', 'editor'] },
  { id: 3, name: 'Charlie', roles: ['admin'] }
]
*/

Chaining filter() and map() for combined filtering.