JavaScript: filter array of objects by another

Viewed 63

I'm trying to filter some objects based on another array of objects. So I'm getting data from an API. These are for example receipts:

[
  {
    "id": 1,
    "name": "test",
    "category": {
        "id": 1,
        "name": "Cookies",
    },
  },
  {
    "id": 2,
    "name": "test2",
    "category": {
        "id": 2,
        "name": "Candy",
    },
  }
]

Then I'm trying to filter the objects on the category name based on another array of categories. I've created a function for this:

function onSelectCategory(category) {
  let receiptsList = receipts.filter((a) =>
    a.category.includes(category.name)
  );
  setReceiptsView(receiptsList);
  setSelectedCategory(category);
}

const category = [ { "id": 2, "name": "Candy" } ];
onSelectCategory(category);

When I run this function, I get an empty Array []. I can't really figure out what I'm doing wrong.

2 Answers

Since the param seems to be an array of objects, you need to use Array#some for comparison instead:

const receipts = [
  { "id": 1, "name": "test", "category": { "id": 1,  "name": "Cookies" } },
  { "id": 2, "name": "test2", "category": { "id": 2, "name": "Candy" } }
];
const categories = [ { "id": 2, "name": "Candy" } ];

const receiptsList = receipts.filter(({ category }) => 
  categories.some(({ name }) => name === category.name)
);

console.log(receiptsList);

Another solution using Set:

const receipts = [
  { "id": 1, "name": "test", "category": { "id": 1,  "name": "Cookies" } },
  { "id": 2, "name": "test2", "category": { "id": 2, "name": "Candy" } }
];
const categories = [ { "id": 2, "name": "Candy" } ];

const categorySet = new Set(categories.map(({ name }) => name));

const receiptsList = receipts.filter(({ category }) => 
  categorySet.has(category.name)
);

console.log(receiptsList);

Assuming that category (the parameter) is a string, the issue is that you are attempting to get the attribute name from the string, when you should be comparing the string to the object.

Try this:

a.category.name == category;

instead of

a.category.includes(category.name)

I may be wrong aboout assuming that category is a string, please clarify by telling us what the parameter category is equal to.

Related