I want to filter one array of objects using another array of object, like in the following code snippet:
const entries = [{
"id" : 1,
"name" : "Entry 1",
"topics" : [ {
"id" : 101,
"name" : "topic 1.1"
}, {
"id" : 102,
"name" : "topic 1.2"
}, {
"id" : 103,
"name" : "topic 1.3"
}]
}, {
"id" : 2,
"name" : "Entry 2",
"topics" : [ {
"id" : 201,
"name" : "topic 2.1"
}, {
"id" : 202,
"name" : "topic 2.2"
}, {
"id" : 203,
"name" : "topic 2.3"
}]
}, {
"id" : 3,
"name" : "Entry 3",
"topics" : [ {
"id" : 25,
"name" : "topic 3.1"
}, {
"id" : 26,
"name" : "topic 3.2"
} ]
}];
const filters = [{
"id" : 1,
"topics" : [ {
"id" : 101,
}, {
"id" : 102,
}]
}, {
"id" : 2,
"topics" : []
}];
const result = entries.filter(
({ id, topics }) =>
filters.some(
({ id: idFromFilteres, topics: topicsFromFilters }) => idFromFilteres === id && topicsFromFilters.length > 0,
) ,
).map(({ id, topics, ...rest }) => ({
id,
topics: topics?.filter(({ id: topicId }) =>
filters.some(
({ topics: topicsFromFilter }) =>
topicsFromFilter.some(
({ id: topicIdFromFilter }) => topicIdFromFilter === topicId,
),
),
),
...rest
}));
console.log(result);
The code is working fine, but I don’t like how I’m iterating again the entries
array to filter the topics
, notice that also entries with empty topics
get filtered as well.
Is there a way to filter this array using one single iteration?
2
Answers
How about
filter
andmap
functions:filter
: remove entries without matching filter topicsmap
: filter topics for the remaining entriesYou can use
reduce()
to to iterate over the entries array and filter it based on the filters array.Example