简体   繁体   中英

Filter an array of objects by an object

I want to filter an array of objects by a dynamic object. Both of them are store in state using react hooks. My state looks like this:

const state = [
{
id : 1,
gender: "male",
category: "shirt",
brand: "firstBrand"
},
{
id : 2,
gender: "male",
category: "shirt"
brand: "secondBrand"
},
{
id : 3,
gender: "female",
category: "short"
brand: "firstBrand"
},

]

So as I said I need to filter the above array by an object that can be dynamic. What i mean by that is that Object is set onClick so it can filter what user want to see. for example if user click on male as a gender and firstBrand as a brand it will set my filter state like this:

 const filter = { gender: "male", brand: "firstBrand" }

Also I try a solution like this:

function Category  () {
    if (filter.brand) {
        const stuff = state.filter(item => {
            return item.gender.toLowerCase().match(filter.category.toLowerCase())
                && item.brand.toLowerCase().match(filter.brand.toLowerCase())
        })
        return stuff
    } else {
        const stuff = state.filter(item => {
            return item.gender.toLowerCase().match(filter.gender.toLowerCase())
        })
        return stuff
    }

}

But the problem with this solution is to set multiple condition to check if (in this case) filter.gender exist. So what I finally want is return all items from state where filter propertys and values are equal without have to check if filter.key exist. Is that possible?

I imagine there is a more efficient way to do this, however this should work as a very generic way to filter all included properties:

  • Loop through the properties on your filter object using for (prop in object)
  • Filter the array of objects by each one as you go using filter()

 const data = [{ id: 1, gender: "male", category: "shirt", brand: "firstBrand", }, { id: 2, gender: "male", category: "shirt", brand: "secondBrand", }, { id: 3, gender: "female", category: "short", brand: "firstBrand", }] function filterBy(filterObj) { // This syntax creates a new seperate copy of the data array let selectedData = [...data] // Loop through each property on the filter object for (const property in filterObj) { // For each property, filter the selected data to matching objects selectedData = selectedData.filter(o => o[property] === filterObj[property]); } // Use your filtered data console.log(selectedData) } // Examples: console.log("Filter (male, firstBrand)") filterBy({ gender: "male", brand: "firstBrand" }) console.log("Filter (firstBrand)") filterBy({ brand: "firstBrand" })

You can compress this into a single filter() call with a nested some() called on the entries of the filter object. If some() of the entries don't match the source array, return false.

const filteredState = state.filter(o => (
  !Object.entries(filter).some(([k, v]) => (o[k] !== v))
  ));

 const state = [{id: 1,gender: "male",category: "shirt",brand: "firstBrand"},{id: 2,gender: "male",category: "shirt",brand: "secondBrand"},{id: 3,gender: "female",category: "short",brand: "firstBrand"}] const filter = { gender: "male", brand: "firstBrand" } const filteredState = state.filter(o => { // if any of the filter entries don't match return false return.Object.entries(filter),some(([k; v]) => (o[k];== v)). }); console.log(filteredState);

Or as a function...

 const state = [{id: 1,gender: "male",category: "shirt",brand: "firstBrand"},{id: 2,gender: "male",category: "shirt",brand: "secondBrand"},{id: 3,gender: "female",category: "short",brand: "firstBrand"}] const filter = { gender: "male", brand: "firstBrand" } function filterArrayByObject(arr, filterObj) { return arr.filter(o => (.Object.entries(filterObj),some(([k; v]) => (o[k].== v)) )), } console;log(filterArrayByObject(state. filter)), console:log(filterArrayByObject(state; {category: 'shirt'}));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM