0

Consider the below array of posts:

posts_array =
[
 {
  id: 1,
  categories: [
   {
    category_id: 1,
    category_name: "one"
   },
   {
    category_id: 2,
    category_name: "two"
   },
 },
 {
  id: 2,
  categories: [
   {
    category_id: 1,
    category_name: "one"
   },
   {
    category_id: 3,
    category_name: "three"
   },
 },
 {
  id: 3,
  categories: [
   {
    category_id: 1,
    category_name: "one"
   },
   {
    category_id: 4,
    category_name: "four"
   },
   {
    category_id: 5,
    category_name: "five"
   },
 }    
]

I then have an array of category ids which I want to filter the above array with:

const category_id_array = [1, 4];

I would like to filter so that all conditions are met, i.e. return elements in posts_array that include both categories.category_id = 1 and categories.category_id = 4

I have tried with the below (with the .some function) but it returns elements where either condition is met, i.e. either categories.category_id = 1 or categories.category_id = 4

function filterPostsByCategoryIds(category_id_array){
    const filter_categories = category_id_array;
    const custom_filter = d => d.categories.some(c => filter_categories.includes(c.category_id));
    const filtered_posts_array = posts_array.filter(custom_filter);
    return filtered_posts_array;
}

Swapping .some with .every does not return any elements at all.

How can I filter posts_array by category_id_array, so that it returns the last element in the above example array, i.e. where categories include all category_id's from category_id_array?

Thanks and stay safe!

1 Answer 1

1

You can use .every() on your category_id_array and return true when there is .some() object within the current .categories which has an category_id equal to that of the current id (c) from your category_id_array:

const posts_array = [{ id: 1, categories: [{ category_id: 1, category_name: "one" }, { category_id: 2, category_name: "two" } ], }, { id: 2, categories: [{ category_id: 1, category_name: "one" }, { category_id: 3, category_name: "three" } ], }, { id: 3, categories: [{ category_id: 1, category_name: "one" }, { category_id: 4, category_name: "four" }, { category_id: 5, category_name: "five" } ], }];

function filterPostsByCategoryIds(category_id_array) {
  const custom_filter = d => category_id_array.every(c => d.categories.some(o => o.category_id === c));
  const filtered_posts_array = posts_array.filter(custom_filter);
  return filtered_posts_array;
}

const res = filterPostsByCategoryIds([1, 4]);
console.log(res);

You could also create a set of category_id for each object and then use .every() with .has() to check that the categories array has every id from the category_id like so:

const posts_array = [{ id: 1, categories: [{ category_id: 1, category_name: "one" }, { category_id: 2, category_name: "two" } ], }, { id: 2, categories: [{ category_id: 1, category_name: "one" }, { category_id: 3, category_name: "three" } ], }, { id: 3, categories: [{ category_id: 1, category_name: "one" }, { category_id: 4, category_name: "four" }, { category_id: 5, category_name: "five" } ], }];

function filterPostsByCategoryIds(category_id_array) {
  return posts_array.filter(({categories}) => {
    const cat_ids = new Set(categories.map(({category_id}) => category_id));
    return category_id_array.every(id => cat_ids.has(id));
  });
}

const res = filterPostsByCategoryIds([1, 4]);
console.log(res);

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.