Home > Enterprise >  How to filter object with multiple optionnal conditions?
How to filter object with multiple optionnal conditions?

Time:05-09

Hi guys i have this array of object

[{name: "John", surname: "Doe", car: "BWM"}, 
 {name: "Louis", surname: "Vuitton", car: "MERCEDES"}, 
 {name: "Bob", surname: "Ross", car: "FORD"}, 
 {name: "Dylan", surname: "James", car: "FERRARI"},
 {name: "Damien", surname: "Rivers", car: "JAGUAR"},]

And i have this code

return this._object.filter(object => object.car === params1 && object.car === params2  && object.car=== params3)

params can be what ever brand car, but they are optionnal besides params1, user can provide only params1 and let the other two undefined.

Params are selected by the user on a select html option, he can choose up to 3 car brand, so 3 params and i pass it as url parameters and pass these paramaters to my function

So i want to do something like in one line : if params2 and params3 exists dont change the code snippet, if they dont exist, only do the filter on params1

Example 1: if params1 = BMW and params 2-3 = undefined it would return this object {name: "John", surname: "Doe", car: "BWM"}

Example 2: if params1 = BMW, params2 = MERCEDES it would return this result : {name: "John", surname: "Doe", car: "BWM"} {name: "Louis", surname: "Vuitton", car: "MERCEDES"},

Same concept with params 3 == FERRARI

I cant see how can i do that with few lines/one line, besides doing if statement everywhere

Thanks !

CodePudding user response:

you can do something like this

const filterData = (data, ...params) => data.filter(d => params.includes(d.car))



const data = [{name: "John", surname: "Doe", car: "BMW"}, 
 {name: "Louis", surname: "Vuitton", car: "MERCEDES"}, 
 {name: "Bob", surname: "Ross", car: "FORD"}, 
 {name: "Dylan", surname: "James", car: "FERRARI"},
 {name: "Damien", surname: "Rivers", car: "JAGUAR"},]
 
 
 console.log(filterData(data, 'BMW'))
 console.log(filterData(data, 'BMW', 'MERCEDES'))
 

CodePudding user response:

You can make the code even more flexible. Instead of passing 3 different params, pass an array like below.

let cars = ["BMW", "MERCEDES"];

now you can check it using javascript's includes method.

return this._object.filter(object => cars.includes(object.car))

CodePudding user response:

By using Array.prototype.includes() you can check against a number of target expressions. It will return true if the argument is equal to at least one element of the array.

In an initial args.map() loop I make sure that the input values are all upper case.

const data=[{name: "John", surname: "Doe", car: "BMW"}, 
 {name: "Louis", surname: "Vuitton", car: "MERCEDES"}, 
 {name: "Bob", surname: "Ross", car: "FORD"}, 
 {name: "Dylan", surname: "James", car: "FERRARI"},
 {name: "Damien", surname: "Rivers", car: "JAGUAR"}];

function filt(...args){
 args=args.map(a=>a.toUpperCase());
 return data.filter(d=>
  args.includes(d.car))
}

console.log(filt("BMW","Mercedes"));
console.log(filt("jaguar"))

CodePudding user response:

First param is an array of objects, second, third, and so on is a rest operator that will accept zero or more values. Once passed into the function it will be an array:

const findValues = (objArray, ...vals) => //...

Next .flatMap() iterates over the object array. On each object, Object.entries() converts it into an array of pairs:

objArray.flatMap(obj => Object.entries(obj) //...
/* {name: "John", surname: "Doe", car: "BWM"} converted into 
   [["name", "John"], ["surname", "Doe"], ["car", "BWM"]] */

Each array of pairs is then taken by .flatMap() and on each iteration it each of it's values will be compared to the vals array (second parameter with rest operator). Note that the vals array was converted to lowercase by .map() as well as each value of the array of pairs because .includes() is case sensitive. The comparison is a ternary .includes() returns true then the object (not the array of pairs) is returned and if false, an empty array is returned (.flatMap() returns an array then flattens it by one level, so returning an empty array is essentially returning nothing).

.flatMap(([key,val]) => 
[...vals].map(val => val.toLowerCase())
.includes(val.toLowerCase()) ? obj : []));

This function will accept any number of values to search, and it's case-insensitive.

const data=[{name:"John",surname:"Doe",car:"BWM"},{name:"Louis",surname:"Vuitton",car:"MERCEDES"},{name:"Bob",surname:"Ross",car:"FORD"},{name:"Dylan",surname:"James",car:"FERRARI"},{name:"Damien",surname:"Rivers",car:"JAGUAR"}];

const findValues = (objArray, ...vals) => objArray.flatMap(obj => Object.entries(obj).flatMap(([key, val]) => [...vals].map(val => val.toLowerCase()).includes(val.toLowerCase()) ? obj : []));

console.log(findValues(data, "JAgUAR", "Dylan"));
console.log('==================');
console.log(findValues(data, "ford", "Dylan", "vuitton", "rivers"));

  • Related