filter()

The filter() method creates a new array containing all elements from the original array that pass a test. This test is set using a provided function. The original array is not modified, and returns only the elements that satisfy the condition.

Syntax

const newArray = array.filter(function(currentValue, index, array) {
  // return true to add the element to new array, otherwise false
});

Parameters:

  • function: Function that tests each element of the array, taking three possible arguments:
    • currentValue: The current element being processed.
    • index (optional): The index of the current element.
    • array (optional): The original array filter() was called upon.

Basic usage

Let's look at a simple filtering example using a pizza toppings array:

const pizzaToppings = ['Cheese', 'Pepperoni', 'Mushrooms', 'Olives', 'Anchovies', 'Pineapple'];

// Filter out controversial toppings
const traditionalToppings = pizzaToppings.filter(topping => {
  return topping !== 'Anchovies' && topping !== 'Pineapple';
});

console.log(traditionalToppings);
// Output: ['Cheese', 'Pepperoni', 'Mushrooms', 'Olives']

Here's an example filtering toppings based on their length:

const pizzaToppings = ['Cheese', 'Pepperoni', 'Mushrooms', 'Olives', 'Anchovies', 'Pineapple'];

// Filter toppings with names longer than 6 characters
const longNameToppings = pizzaToppings.filter(topping => {
  return topping.length > 6;
});

console.log(longNameToppings);
// Output: ['Pepperoni', 'Mushrooms', 'Anchovies', 'Pineapple']

Using the index parameter

The second parameter gives you access to the current index:

const pizzaToppings = ['Cheese', 'Pepperoni', 'Mushrooms', 'Olives', 'Anchovies', 'Pineapple'];

// Filter toppings at even index positions
const evenIndexToppings = pizzaToppings.filter((topping, index) => {
  return index % 2 === 0;
});

console.log(evenIndexToppings);
// Output: ['Cheese', 'Mushrooms', 'Anchovies']

The following example will remove any duplicate values:

const pizzaToppings = ['Cheese', 'Pepperoni', 'Cheese', 'Mushrooms', 'Olives', 'Anchovies', 'Pineapple'];

// Filter toppings to keep only the first occurrence of each
const uniqueToppings = pizzaToppings.filter((topping, index, array) => {
  return array.indexOf(topping) === index;
});

console.log(uniqueToppings);
// Output: ["Cheese","Pepperoni","Mushrooms","Olives","Anchovies","Pineapple"]
// (This keeps the first occurrence of each topping and removes duplicates)

The function can also be extracted from the filter method, making it more readable and re-usable:

const pizzaToppings = ['Cheese', 'Pepperoni', 'Mushrooms', 'Olives', 'Anchovies', 'Pineapple'];

const isVegetarian = (topping) => {
  const meatToppings = ['Pepperoni', 'Anchovies', 'Bacon', 'Sausage'];
  return !meatToppings.includes(topping);
}

const vegetarianToppings = pizzaToppings.filter(isVegetarian);

console.log(vegetarianToppings);
// Output: ['Cheese', 'Mushrooms', 'Olives', 'Pineapple']

Using the array parameter

The third parameter provides reference to the original array:

const pizzaOrders = [
  { type: "Margherita", price: 8 },
  { type: "BBQ Chicken", price: 15 },
  { type: "Veggie", price: 9 },
];

// Function to filter orders that cost more than 10
const expensiveOrders = pizzaOrders.filter((order, index, originalArray) => {
  console.log(`Checking order: ${order.type}`);
  console.log(`Index: ${index}`);
  console.log(`Original Array:`, originalArray);

  // Return only orders where price is greater than 10
  return order.price > 10;
});

console.log("Original Orders:", pizzaOrders);
console.log("Expensive Orders:", expensiveOrders);

Working with objects in arrays

The filter() method is useful when working with arrays of objects. The following exmaple will filter all vegetarian pizzas from the objects:

const pizzaMenu = [
  { name: 'Margherita', price: 10, isVegetarian: true },
  { name: 'Pepperoni', price: 12, isVegetarian: false },
  { name: 'Vegetarian', price: 13, isVegetarian: true },
  { name: 'Supreme', price: 15, isVegetarian: false },
  { name: 'Hawaiian', price: 12, isVegetarian: false }
];

// Find all vegetarian pizzas
const vegetarianPizzas = pizzaMenu.filter(pizza => pizza.isVegetarian);

console.log(vegetarianPizzas);
/* Output:
[
  { name: 'Margherita', price: 10, isVegetarian: true },
  { name: 'Vegetarian', price: 13, isVegetarian: true }
]
*/

This example will find pizzas under $13:

const pizzaMenu = [
  { name: 'Margherita', price: 10, isVegetarian: true },
  { name: 'Pepperoni', price: 12, isVegetarian: false },
  { name: 'Vegetarian', price: 13, isVegetarian: true },
  { name: 'Supreme', price: 15, isVegetarian: false },
  { name: 'Hawaiian', price: 12, isVegetarian: false }
];
// Find affordable pizzas (less than $13)
const affordablePizzas = pizzaMenu.filter(pizza => pizza.price < 13);

console.log(affordablePizzas);
/* Output:
[
  { name: 'Margherita', price: 10, isVegetarian: true },
  { name: 'Pepperoni', price: 12, isVegetarian: false },
  { name: 'Hawaiian', price: 12, isVegetarian: false }
]
*/

Chaining filter() with other array methods

A useful feature of filter() is the ability to chain it with other array methods:

const pizzaMenu = [
  { name: 'Margherita', price: 10, isVegetarian: true },
  { name: 'Pepperoni', price: 12, isVegetarian: false },
  { name: 'Vegetarian', price: 13, isVegetarian: true },
  { name: 'Supreme', price: 15, isVegetarian: false },
  { name: 'Hawaiian', price: 12, isVegetarian: false }
];

// Find names of vegetarian pizzas that cost less than $13
const affordableVegetarianPizzaNames = pizzaMenu
  .filter(pizza => pizza.isVegetarian && pizza.price < 13)
  .map(pizza => pizza.name);

console.log(affordableVegetarianPizzaNames);
// Output: ['Margherita']

Filtering nested arrays

You can use filter() with nested arrays and combine it with other methods:

const pizzaStores = [
  {
    name: "Store 1",
    pizzas: [
      { name: "Margherita", price: 10, isVegetarian: true },
      { name: "Pepperoni", price: 12, isVegetarian: false },
      { name: "Supreme", price: 15, isVegetarian: false }
    ]
  },
  {
    name: "Store 2",
    pizzas: [
      { name: "Margherita", price: 11, isVegetarian: true },
      { name: "Vegetarian", price: 13, isVegetarian: true },
      { name: "Hawaiian", price: 12, isVegetarian: false }
    ]
  }
];

// Find stores that offer vegetarian options
const storesWithVegetarianOptions = pizzaStores.filter(store => {
  return store.pizzas.some(pizza => pizza.isVegetarian);
});

console.log(storesWithVegetarianOptions.map(store => store.name));
// Output: ["Store 1", "Store 2"]

// Find stores that offer ONLY vegetarian pizzas
const vegetarianOnlyStores = pizzaStores.filter(store => {
  return store.pizzas.every(pizza => pizza.isVegetarian);
});

console.log(vegetarianOnlyStores.map(store => store.name));
// Output: [] (no stores offer only vegetarian pizzas)

Practical example: order filtering

const pizzaOrder = [
  { name: 'Margherita', price: 10, quantity: 2, isReady: true },
  { name: 'Pepperoni', price: 12, quantity: 1, isReady: false },
  { name: 'Supreme', price: 15, quantity: 1, isReady: true },
  { name: 'Vegetarian', price: 13, quantity: 3, isReady: false }
];

// Find ready items to be delivered
const readyItems = pizzaOrder.filter(item => item.isReady);
console.log("Ready for delivery:", readyItems.map(item => `${item.quantity}x ${item.name}`));
// Output: Ready for delivery: ["2x Margherita", "1x Supreme"]

// Find items still being prepared
const pendingItems = pizzaOrder.filter(item => !item.isReady);
console.log("Still preparing:", pendingItems.map(item => `${item.quantity}x ${item.name}`));
// Output: Still preparing: ["1x Pepperoni", "3x Vegetarian"]

// Calculate total of ready items
const totalReadyValue = readyItems.reduce((total, item) => total + (item.price * item.quantity), 0);
console.log(`Value of ready items: $${totalReadyValue}`);
// Output: Value of ready items: $35

When to use filter() vs. other methods

Use filter() when:

  • You want to exclude certain elements based on a criteria in the provided function.
  • You need to extract elements from the original array based on a condition.
  • You need a subset of the original array elements.

Consider using other methods when:

  • You need to transform each element (use map()).
  • You need to perform an action without creating a new array (use forEach()).
  • You need to accumulate a value (use reduce()).
  • You need to find just the first matching element (use find()).
  • You need to check if any/all elements match a condition (use some() or every()).

Conclusion

The filter() method is ideal for extracting elements from arrays based on conditions. By returning a new array with only the elements that pass a test, filter() enables you to create subsets of data without modifying the original array. It can also be combined with other array methods, providing a flexible way to work with arrays in JavaScript.