Return object from filter when one of the values matches

I am working on a personal project where I have a dropdown filter that displays cards based on the category. Some cards have multiple category descriptions. I am trying to filter the results based off the select options. I am having trouble selecting any objects that contain the categories in the dropdown. I am easily able to do this if it only has one category, but if it was multiple it will not work.

How do you go about that? Here is some test code to illustrate my intentions.
In the rest code I want to return all objects that have a pet category

  const filteredResults = [
    {
    name: 'George',
    height: `6'1`,
    weight: '230lbs',
    pets: ['dog, cat']
  }, {
    name: 'Carl',
    height: `6'1`,
    weight: '230lbs',
    pets: ['mouse']
  }, {
    name: 'Jeff',
    height: `6'1`,
    weight: '230lbs',
    pets: ['penguin, cat']
  }, {
    name: 'Harry',
    height: `6'1`,
    weight: '230lbs',
    pets: ['horse, cat']
  }, {
    name: 'Larry',
    height: `6'1`,
    weight: '230lbs',
    pets: ['goat, horse']
  }, {
    name: 'Tom',
    height: `6'1`,
    weight: '230lbs',
    pets: ['rat, pig']
  }, {
    name: 'Stacy',
    height: `6'1`,
    weight: '230lbs',
    pets: ['fish, cat']
  }, {
    name: 'John',
    height: `6'1`,
    weight: '230lbs',
    pets: ['dog, monkey']
  }, {
    name: 'Tim',
    height: `6'1`,
    weight: '230lbs',
    pets: ['dog, tiger']
  },
  ]
  
  
  let updatedList = filteredResults.filter(item => {
    
    return item.name === 'Tim'
  })

   let updatedList2 = filteredResults.filter(item => {
    
    return item.pets === 'cat'
  })

  console.log(updatedList);
  console.log(updatedList2);

This is because you are trying to compare the string ‘cat’ to an array reference/pointer.

To address this, the comparison should be item.pets[0] === 'cat'

But in your case, that will still not work. This is because in the pets array, there is a single element at pets[0] that is a single string
"dog, cat".

Is this intentional or did you mean for it to be ['cat', 'dog']?

if it is intentional, then you could do an pets[0].indexOf('cat').

If the substring 'cat' is not found in the string 'dog, cat', then indexOf() will return -1 .
So the code to compare the array 'pets' looks like:

return  item.pets[0].indexOf('cat')  >=  0
1 Like

it was definitely not intentional to write ["dog, cat"] , I meant ["dog", "cat"] . Thank you for pointing that out.

The data I am using does not have a set number of categories. It could be 1 it could be 4. I want to iterate through to tell, but am having a hard time connecting the dots.

Here is a sample of two of the objects from the data to give you an idea. (tags is what I am looking for)

    "_id": "XtZMaD2s28",
    "author": "Thomas Edison",
    "content": "If we all did the things we are capable of doing, we would literally astound ourselves.",
    "tags": ["Inspirational", "Motivational"],
    "authorSlug": "thomas-edison",
    "length": 87,
    "dateAdded": "2023-04-14",
    "dateModified": "2023-04-14"
  },
  {
    "_id": "R1DmP1kYtW",
    "author": "Charles Dickens",
    "content": "Reflect on your present blessings, of which every man has many; not on your past misfortunes, of which all men have some.",
    "tags": ["Gratitude"],
    "authorSlug": "charles-dickens",
    "length": 121,
    "dateAdded": "2023-04-14",
    "dateModified": "2023-04-14"
  },

here is some code I’ve tried, but updatedList always logs an en empty array

  let updatedList = filteredResults.filter(item => {
   item.tags.map(index => {
      return index === category
    })
    return item;
   });

'category ’ is dynamically set to be the value of one of the selectable categories

I figured out how to do it. Though I really wanted to look a dynamic way like you showed for the other example, I will have to make do with it slightly being hard coded. Your suggestion helped me think in the right direction. thank you

 let updatedList = shorterQuotes.filter((item) => {
  return item.tags[2] ?  ( item.tags[0] === category ||
  item.tags[1] === category 
  ||
  item.tags[2] === category) :  (item.tags[0] === category || item.tags[1] === category)

})

Then how about this:

const database = [
  {
    name: "George",
    height: `6'1`,
    weight: "230lbs",
    pets: ["dog", "cat"],
  },
  {
    name: "Carl",
    height: `6'1`,
    weight: "230lbs",
    pets: ["mouse"],
  },
  {
    _id: "XtZMaD2s28",
    author: "Thomas Edison",
    content:
      "If we all did the things we are capable of doing, we would literally astound ourselves.",
    tags: ["Inspirational", "Motivational"],
    authorSlug: "thomas-edison",
    length: 87,
    dateAdded: "2023-04-14",
    dateModified: "2023-04-14",
  },
  {
    _id: "R1DmP1kYtW",
    author: "Charles Dickens",
    content:
      "Reflect on your present blessings, of which every man has many; not on your past misfortunes, of which all men have some.",
    tags: ["Gratitude"],
    authorSlug: "charles-dickens",
    length: 121,
    dateAdded: "2023-04-14",
    dateModified: "2023-04-14",
  },
];



let filteredResults = database.filter(object => {
  return customIncludes(object, "pets", "cat"); 
});

/* Takes a single object  and checks it to 
   see if it has a 'property' with a specific 'value'. 
   Returns false if the value and/or property does not exist. */
function customIncludes(obj, property, value) {
  if (!obj.hasOwnProperty(property)) {
    return false;
  }

  if (Array.isArray(obj[property])) {
    if (obj[property].includes(value)) {
      return true;
    }
  } else if (obj[property] === value) {
    return true;
  } else {
    return false;
  }
}


console.log(filteredResults);

There are other ways that this filter method could be implemented, but I will stick with this so that it will be clear what is going on.

To further spice things up, you could even create a wrapper function for database.filter():

let filteredResults = filterWrapper(database, "pets", "cat");

function filterWrapper(arrayOfObjects, key, value) {
  return arrayOfObjects.filter((object) => {
    return customIncludes(object, key, value);
  });
}
1 Like

This was perfect. Thank you for your reply, I learned something new and now my code is fully dynamic

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.