Boky Boky - 2 months ago 8
Javascript Question

Filter through two arrays of objects

I have two arrays and I want to filter through one array with a values of another array. Thus, I have cars array and I want to filter through cars with values of filter array. My code is as follows :

let cars = [
{name: "Audi", price: "1000", transmission: "Manual"},
{name: "Golf", price: "2000", transmission: "Manual"},
{name: "Passat", price: "3000", transmission: "Automatic"},
{name: "Seat", price: "4000", transmission: "Manual"}
];

let filters = [
{searchFilter : ["price", 2000, 3000]},
{searchFilter : ["transmission", "", "automatic"]},
];

let carsToShow = "";

let result = cars.filter ( c => {
let carsToShow = "";
return filters.filter( f => {
if(f.searchFilter[0] === "price"){
carsToShow = c.price >= f.searchFilter[1] && c.price <= f.searchFilter[2]
}

if(f.searchFilter[0] === "transmission"){
if(f.searchFilter[1] !== ""){
carsToShow = c.transmission.toLowerCase() === "manual"
}

if(f.searchFilter[2] !== ""){
carsToShow = c.transmission.toLowerCase() === "automatic"
}
}

return carsToShow;
})

})

console.log(result);


In this case the result should be
{name: "Passat", price: "3000", transmission: "Automatic"}
. But it doesn't work.

Any suggestion?

Answer

The first thing I'd do is structure the entries in the filters so the [0] entry of the array isn't special:

let filters = [
  {filter: "price", values: [2000, 3000]},
  {filter: "transmission", values: ["", "automatic"]},
];

Ideally, the data would be consistent in terms of using numbers or strings for price rather than using numbers in one place and strings in another, but I'm going to assume that's a design constraint.

Then it's a matter of weeding out the entries where any filter doesn't match: So for each car, we use filters.some to find a filter entry that doesn't match:

let result = cars.filter(c => !filters.some(f => {
  let value = c[f.filter].toLowerCase();
  return f.values.findIndex(v => v == value) == -1;
}));

Live Copy:

let cars = [
    { name: "Audi",  price: "1000", transmission: "Manual" },
    { name: "Golf", price: "2000", transmission: "Manual" },
    { name: "Passat", price: "3000", transmission: "Automatic" },
    { name: "Seat", price: "4000", transmission: "Manual" }
];

let filters = [
  {filter: "price", values: [2000, 3000]},
  {filter: "transmission", values: ["", "automatic"]},
];

//let carsToShow = "";     <== This wasn't used for anything

let result = cars.filter(c => !filters.some(f => {
  let value = c[f.filter].toLowerCase();
  return f.values.findIndex(v => v == value) == -1;
}));

console.log(result);

Note I'm using loose equality in the findIndex call (which is why it's not just indexOf), so that 2000 == "2000". But again, ideally the data and the filter would have the same type so we could use

return f.values.inexOf(value) == -1;

instead.

Comments