使用多个过滤条件过滤对象数组

Filtering an array of objects with multiple filter conditions

假设我有一个对象数组:

let users = [{
 name: "Mark",
 location: "US",
 job: "engineer"
},
{
 name: "Mark",
 location: "US",
 job: "clerk"
},
{
 name: "Angela",
 location: "Europe",
 job: "pilot"
}, 
{
 name: "Matthew",
 location: "US",
 job: "engineer"
}]

我有一个过滤器对象,其中包含我要过滤数据的所有类别(每个键可以有多个值):

const filters = {
  name: ["Mark", "Matthew"],
  location: ["US"],
  job: ["Engineer"]
}

根据这些过滤器和数据,预期结果为 return:

[{name: "Mark", location: "US", job: "Engineer"}, {name: "Matthew", location: "US", job: "Engineer"}]

我尝试过过滤:

users.filter(user => {
  for(let k in filters) {
    if(user[k] === filters[k]) {
      return true;
    }
  }
})

但是,此方法没有考虑到过滤器类别可能包含多个值,我可以通过以下方式处理这些值:

filters[k][0] or filters[k][1]

但它不是动态的。

如果有人有任何意见,我们将不胜感激!谢谢。

filters 上使用 Object.entries() 以获得 [key, values] 对的数组。用 Array.every() 迭代对,并检查每个对是否包含当前对象的值。

const fn = (arr, filters) => {
  const filtersArr = Object.entries(filters)
  
  return arr.filter(o => 
    filtersArr.every(([key, values]) => 
      values.includes(o[key])
    )
  )
}

const users = [{"name":"Mark","location":"US","job":"engineer"},{"name":"Mark","location":"US","job":"clerk"},{"name":"Angela","location":"Europe","job":"pilot"},{"name":"Matthew","location":"US","job":"engineer"}]

const filters = {
  name: ["Mark", "Matthew"],
  location: ["US"],
  job: ["engineer"]
}

const result = fn(users, filters)

console.log(result)

使用 Array.includes() 的一个警告是大小写的差异会提供 false 答案(Engineerengineer 在这种情况下)。要解决此问题,请使用不区分大小写的搜索标志 (i) 将当前单词转换为 RegExp,并使用 Array.some() 检查它是否适合数组中的任何单词。

const fn = (arr, filters) => {
  const filtersArr = Object.entries(filters)
  
  return arr.filter(o => 
    filtersArr.every(([key, values]) => {
      const pattern = new RegExp(`^${o[key]}$`, 'i')
    
      return values.some(v => pattern.test(v))
    })    
  )
}

const users = [{"name":"Mark","location":"US","job":"engineer"},{"name":"Mark","location":"US","job":"clerk"},{"name":"Angela","location":"Europe","job":"pilot"},{"name":"Matthew","location":"US","job":"engineer"}]

const filters = {
  name: ["Mark", "Matthew"],
  location: ["US"],
  job: ["Engineer"]
}

const result = fn(users, filters)

console.log(result)

您可以遍历过滤器对象的条目并确保每个键的值都是允许的值之一。

let users = [{name:"Mark",location:"US",job:"Engineer"},{name:"Mark",location:"US",job:"clerk"},{name:"Angela",location:"Europe",job:"pilot"},{name:"Matthew",location:"US",job:"Engineer"}];
const filters = {
  name: ["Mark", "Matthew"],
  location: ["US"],
  job: ["Engineer"]
};
const res = users.filter(o => 
  Object.entries(filters).every(([k,v])=>v.includes(o[k])));
console.log(res);