Match multiple object fields with an input value in JS

Viewed 99

I am working on a large product datasets and I need to filter through the products list based on the user's input value. My product dataset looks something like this:

const products = [
  {id: 0, name: "Product1", brand: "Theraflu", itemCode: "THE110", price: 5.45},
  {id: 1, name: "Product2", brand: "Benadryl", itemCode: "BEN121", price: 7.05},
  {id: 2, name: "Product3", brand: "Listerine", itemCode: "LIS204", price: 4.55},
  {id: 3, name: "Product4", brand: "Tylenol", itemCode: "TYL116", price: 6.10},
];

I was able to filter the product list based on the different fields available in each individual product object like this:

const keys = ["name", "brand", "itemCode"];

const getFilteredProducts = (filterText) => {
  const newProducts = products.filter(product => keys.some(key => product[key].toLowerCase().includes(filterText.toLowerCase())));
  
  return newProducts;
}

console.log(getFilteredProducts("Tylenol"));

This code actually works when I filter the product based on individual field. However, when I try to combine different fields like:

console.log(getFilteredProducts("product4 Tylenol"));

The returned value of this is an empty array. Is there a way to achieve this without altering the existing filtering functionality?

1 Answers

Seems like you'll need to search each word of the filterText on its own. Maybe something like this:

const keys = ["name", "brand", "itemCode"];

const getFilteredProducts = (filterText) => {
  const filterWords = filterText.split(" ");
  const newProducts = [];

  for (const word of filterWords) {
    newProducts.push(
      products.filter(product => keys.some(key =>
        product[key].toLowerCase().includes(word.toLowerCase())
      ))
    );  
  }

  return [].concat(...newProducts).filter((value, index, self) => 
    self.findIndex((m) => m.id === value.id) === index
  );
}

console.log(getFilteredProducts("Tylenol Product3"));
Related