I have an array of objects who follow this structure below:
{ "level": 1 "objectId": "3756" "objectIdNo": 35636 "wpId": "3635473" }
I now want to filter an array of these objects by another object. This filterObject
would have the structure below:
// filterObject { level: "2" objectId: "10" wpId: "1" }
But this filterObject
doesn’t always have all the key-value pairs because they get set manually in the UI. As a result the filterObject
can also look like this:
{ level: "2" }
My goal is to return a new array of filteredObjects
who match this filterObject
. When only one filter exists on the filterObject
I want to return all objects that match this one key-value pair. But if more filters exist on the filterObject
I want to return all objects that match both key-value pairs (not only one).
Example:
This is the data I want to filter:
[ { "level": "1" "objectId": "11" "objectIdNo": "320" "wpId": "123" }, { "level": "2" "objectId": "12" "objectIdNo": "321" "wpId": "123" }, { "level": "2" "objectId": "13" "objectIdNo": "322" "wpId": "120" }, ]
1.
If this is my filterObject
:
{ "level": "2" }
Return:
[ { "level": "2" "objectId": "12" "objectIdNo": "321" "wpId": "123" }, { "level": "2" "objectId": "13" "objectIdNo": "322" "wpId": "120" }, ]
2.
If this is my filterObject
:
{ "level": "2", "wpId": "123" }
Return:
[ { "level": "2" "objectId": "12" "objectIdNo": "321" "wpId": "123" }, ]
I hope that explains the logic I want to achieve which I couldn’t implement myself. I would appreciate some ideas or applicable functions.
This is what I already tried in React. The data variable holds the array of objects and the filter variable hold the filterObjects
.
useEffect(() => { if (data) { const filtered = data.filter((task) => { if (!filter) { return true; } return ( task.level === filter.level || task.objectId === filter.objectId || task.wpId === filter.wpId ); }); setFilteredTasks(filtered); } }, [filter]);
With my attempt, if I just set the one filter key-value pair I get an empty array,
Advertisement
Answer
You can achieve this result using filter, Object.keys, and every.
You have to use filter
and pass predicate that tell whether it is included in the final result.
In predicate, loop over all properties on the filters
object and match if it is present in data
or not. Simple
data.filter((o) =>Object.keys(filters).every((k) => filters[k] === o[k]));
const data = [{ level: "1", objectId: "11", objectIdNo: "320", wpId: "123", }, { level: "2", objectId: "12", objectIdNo: "321", wpId: "123", }, { level: "2", objectId: "13", objectIdNo: "322", wpId: "120", }, ]; const filters = { level: "2", wpId: "123", }; const result = data.filter((o) => Object.keys(filters).every((k) => filters[k] === o[k]) ); console.log(result);