Home > Back-end >  Javascript Array of Object: filter by multple AND conditions
Javascript Array of Object: filter by multple AND conditions

Time:12-25

My mocked data:

[
  {
    "id": 1,
    "first_name": "Suzy",
    "last_name": "Pinnell",
    "email": "[email protected]",
    "gender": "Agender",
    "image": "http://dummyimage.com/410x239.png/5fa2dd/ffffff",
    "department": "Marketing",
    "job_title": "Quality Control Specialist",
    "skill": "Residential Homes"
   },
  {
    "id": 2,
    "first_name": "Enriqueta",
    "last_name": "Folbig",
    "email": "[email protected]",
    "gender": "Male",
    "image": "http://dummyimage.com/247x244.png/5fa2dd/ffffff",
    "department": "Sales",
    "job_title": "Environmental Specialist",
    "skill": "MMC"
  },
  {
    "id": 3,
    "first_name": "Simmonds",
    "last_name": "Acomb",
    "email": "[email protected]",
    "gender": "Polygender",
    "image": "http://dummyimage.com/315x256.png/dddddd/000000",
    "department": "Human Resources",
    "job_title": "Accountant",
    "skill": "Xilinx"
  },
  {
    "id": 4,
    "first_name": "Bernita",
    "last_name": "Hartman",
    "email": "[email protected]",
    "gender": "Female",
    "image": "http://dummyimage.com/305x275.png/dddddd/000000",
    "department": "Support",
    "job_title": "Account ExecutiveII",
    "skill": "Airframe"
  }
]

I found a similar question here: javascript filter array multiple conditions

To define what to filter they pass an object:

var filter = {
  gender: 'male',
  department: 'Sales'
};

This works. It shows every object containing both keys.

I tried to modify it, so I could use an array:*

var filter = {
  gender: ['Male'],
  department: ['Sales', 'Marketing']
};

My goal is to filter the data by the given values in the array. Only items should appear, which contain all males in sales and marketing.

I tried includes (inside filter and a for in loop), but it shows only the results of the first array, the second one is ignored. I am not sure how to achieve a AND condition inside the arrays for all of them.

Thank you.

CodePudding user response:

You could store all entries in advance to prevent to get for each object of data to get the same entries array of the filters.

Filter entries to remove possible empty arrays.

Then take the entries and check if the value is the one of the data or if the filter contains an array, then check if the filter array contains the value from data.

const
    data = [{ id: 1, first_name: "Suzy", last_name: "Pinnell", email: "[email protected]", gender: "Agender", image: "http://dummyimage.com/410x239.png/5fa2dd/ffffff", department: "Marketing", job_title: "Quality Control Specialist", skill: "Residential Homes" }, { id: 2, first_name: "Enriqueta", last_name: "Folbig", email: "[email protected]", gender: "Male", image: "http://dummyimage.com/247x244.png/5fa2dd/ffffff", department: "Sales", job_title: "Environmental Specialist", skill: "MMC" }, { id: 3, first_name: "Simmonds", last_name: "Acomb", email: "[email protected]", gender: "Polygender", image: "http://dummyimage.com/315x256.png/dddddd/000000", department: "Human Resources", job_title: "Accountant", skill: "Xilinx" }, { id: 4, first_name: "Bernita", last_name: "Hartman", email: "[email protected]", gender: "Female", image: "http://dummyimage.com/305x275.png/dddddd/000000", department: "Support", job_title: "Account ExecutiveII", skill: "Airframe" }],
    filter = { last_name: [], gender: ['Male'], department: ['Sales', 'Marketing'] },
    filterEntries = Object
        .entries(filter)
        .filter(([, v]) => !Array.isArray(v) || v.length),
    result = data.filter(o => filterEntries.every(([k, v]) =>
        o[k] === v ||
        Array.isArray(v) && v.includes(o[k])
    ));

console.log(result);

CodePudding user response:

That's a good every use case :)

const data = [
  {
    "id": 1,
    "first_name": "Suzy",
    "last_name": "Pinnell",
    "email": "[email protected]",
    "gender": "Agender",
    "image": "http://dummyimage.com/410x239.png/5fa2dd/ffffff",
    "department": "Marketing",
    "job_title": "Quality Control Specialist",
    "skill": "Residential Homes"
   },
  {
    "id": 2,
    "first_name": "Enriqueta",
    "last_name": "Folbig",
    "email": "[email protected]",
    "gender": "Male",
    "image": "http://dummyimage.com/247x244.png/5fa2dd/ffffff",
    "department": "Sales",
    "job_title": "Environmental Specialist",
    "skill": "MMC"
  },
  {
    "id": 3,
    "first_name": "Simmonds",
    "last_name": "Acomb",
    "email": "[email protected]",
    "gender": "Polygender",
    "image": "http://dummyimage.com/315x256.png/dddddd/000000",
    "department": "Human Resources",
    "job_title": "Accountant",
    "skill": "Xilinx"
  },
  {
    "id": 4,
    "first_name": "Bernita",
    "last_name": "Hartman",
    "email": "[email protected]",
    "gender": "Female",
    "image": "http://dummyimage.com/305x275.png/dddddd/000000",
    "department": "Support",
    "job_title": "Account ExecutiveII",
    "skill": "Airframe"
  }
]

const filter = {
  gender: ['Male'],
  department: ['Sales', 'Marketing']
}

const result = data.filter(item => (
  Object.entries(filter).every(([key, arr]) => arr.includes(item[key]))
))

console.log(result)

CodePudding user response:

Instead of negating the === operator, you can negate an includes call:

data = data.filter(function(item) {
  for (var key in filter) {
    if (item[key] === undefined || !filter[key].includes(item[key]))
      return false;
  }
  return true;
});

CodePudding user response:

You can acheive your expected result by iterating over your filter object and on the every iteration, checking target object can pass your filter or not (in below snippet I've used Object.entries and every method to do that), like this:

const data = [
  {
    "id": 1,
    "first_name": "Suzy",
    "last_name": "Pinnell",
    "email": "[email protected]",
    "gender": "Agender",
    "image": "http://dummyimage.com/410x239.png/5fa2dd/ffffff",
    "department": "Marketing",
    "job_title": "Quality Control Specialist",
    "skill": "Residential Homes"
   },
  {
    "id": 2,
    "first_name": "Enriqueta",
    "last_name": "Folbig",
    "email": "[email protected]",
    "gender": "Male",
    "image": "http://dummyimage.com/247x244.png/5fa2dd/ffffff",
    "department": "Sales",
    "job_title": "Environmental Specialist",
    "skill": "MMC"
  },
  {
    "id": 3,
    "first_name": "Simmonds",
    "last_name": "Acomb",
    "email": "[email protected]",
    "gender": "Polygender",
    "image": "http://dummyimage.com/315x256.png/dddddd/000000",
    "department": "Human Resources",
    "job_title": "Accountant",
    "skill": "Xilinx"
  },
  {
    "id": 4,
    "first_name": "Bernita",
    "last_name": "Hartman",
    "email": "[email protected]",
    "gender": "Female",
    "image": "http://dummyimage.com/305x275.png/dddddd/000000",
    "department": "Support",
    "job_title": "Account ExecutiveII",
    "skill": "Airframe"
  }
];

const filter = {
  gender: ['Male'],
  department: ['Sales', 'Marketing']
}

const createFilterFun = filters => obj => Object.entries(filters).every( ([k, v]) => v.includes(obj[k]) );
const filterByGenderAndDepratment = createFilterFun(filter);
const result = data.filter(filterByGenderAndDepratment);
console.log(result)

  • Related