Reputation: 324
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!
Upvotes: 0
Views: 156
Reputation: 50954
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);
Upvotes: 1