3

My mocked data:

[
  {
    "id": 1,
    "first_name": "Suzy",
    "last_name": "Pinnell",
    "email": "spinnell0@utexas.edu",
    "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": "efolbig1@google.com.br",
    "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": "sacomb2@amazon.co.uk",
    "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": "bhartman3@whitehouse.gov",
    "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.

5 Answers5

1

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;
});
Mureinik
  • 297,002
  • 52
  • 306
  • 350
  • I tried that. Didn't work. If I have more than one item in the array, there is no result at all. This works: ``` var filter = { gender: ['Male'], department: ['Sales''] }; ``` This doesn't: ``` var filter = { gender: ['Male'], department: ['Sales', 'Marketing'] }; ``` – Vorname Nachname Dec 24 '21 at 18:43
  • @VornameNachname oops, I switch `filter` and `item` after the `||`. Edited and fixed. – Mureinik Dec 24 '21 at 18:45
  • this gives me no results. – Vorname Nachname Dec 24 '21 at 18:53
1

That's a good every use case :)

const data = [
  {
    "id": 1,
    "first_name": "Suzy",
    "last_name": "Pinnell",
    "email": "spinnell0@utexas.edu",
    "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": "efolbig1@google.com.br",
    "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": "sacomb2@amazon.co.uk",
    "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": "bhartman3@whitehouse.gov",
    "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)
Jean Will
  • 543
  • 3
  • 11
1

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: "spinnell0@utexas.edu", 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: "efolbig1@google.com.br", 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: "sacomb2@amazon.co.uk", 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: "bhartman3@whitehouse.gov", 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);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
1

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": "spinnell0@utexas.edu",
    "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": "efolbig1@google.com.br",
    "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": "sacomb2@amazon.co.uk",
    "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": "bhartman3@whitehouse.gov",
    "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)
Saeed Shamloo
  • 6,199
  • 1
  • 7
  • 18
1

try this

var itemsFilter = {
  gender: ['Male'],
  department: ['Sales', 'Marketing']
};
users= users.filter (function(item) {
  var find=false;
  for (var key in itemsFilter) {
   find=false;
   if (item[key] === undefined) return false;
    for (var k in itemsFilter[key]) 
      if (itemsFilter[key][k] == item[key]) find=true;
      if (find==false) return false;
   };
return find;
});
Serge
  • 40,935
  • 4
  • 18
  • 45