Question

Javascript Filter OR AND together

I have an array of objects that I need to filter from another object, which contains the same keys, where the values ​​are arrays. I need it to be considered OR within the same filter array, but if they are different filters, it must be considered AND.

The size of the objects is variable, it can contain 2 or 30 items, so we cannot mention the keys explicitly.

Ex:

#data
[
    {a:'1',b:'2'},
    {a:'3',b:'4'},
    {a:'5',b:'6'}
]

#filter 1
{a:['1','3']}

#result 1
[
    {a:'1',b:'2'},
    {a:'3',b:'4'},
]

#filter 2
{a:['1','3'],b:['2']}

#result 2
[
    {a:'1',b:'2'}
]

I tried to use this code, but the result was not what I expected, it returned everything with OR.

return this.data.filter(
    (objData:any) => {
        return Object.keys(currDataRow).some(
            (keyDataRow:any) => {                       
                if(typeof(objFilter[keyDataRow])!=='undefined') {
                return objFilter[keyDataRow].includes(currDataRow[keyDataRow])                          
            }
                return false;
            }
        )   
    }
)

Then I tried this other result, it improved, but it is still not the expected result because selecting two of the same filter did not return correctly

return this.data.filter(
   (objData:any) => {
        let result = 0;
        let countFilter = 0;
        Object.keys(currDataRow).some(
            (keyDataRow:any) => {                                               
            if(typeof(objFilter[keyDataRow])!=='undefined') {                           
                countFilter += objFilter[keyDataRow].length
            result += objFilter[keyDataRow].includes(currDataRow[keyDataRow]) ? 1 : 0;                          
        }
        }
        )               
        return result == countFilter;
    }
)
 3  55  3
1 Jan 1970

Solution

 2

It will be easier if you iterate the filter key/value pairs and require that every pair of them has a match for the current object:

const applyFilter = (data, filter) => data.filter(obj => 
    Object.entries(filter).every(([key, values]) =>
        values.includes(obj[key])
    )
);

// Example run
const data = [
    { a: '1', b: '2' },
    { a: '3', b: '4' },
    { a: '5', b: '6' }
];
const filter2 = { a: ['1', '3'], b: ['2'] };
const result = applyFilter(data, filter2);
console.log(result);

2024-07-10
trincot