【问题标题】:Filtering an array of objects with multiple filter conditions过滤具有多个过滤条件的对象数组
【发布时间】:2021-07-05 19:28:12
【问题描述】:

假设我有一个对象数组:

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"]
}

根据这些过滤器和数据,预期的结果将返回:

[{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[k].includes(user[k]) ?
  • 而不是 users[k] ===filters[k] 尝试 filters[k].includes(users[k]) 它将在整个数组中寻找相似之处..我正在写这个虽然来自我的手机,但在语法上可能有点偏离
  • @Jonas heh 打败了我!实际上最好的答案

标签: javascript arrays object filtering


【解决方案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)。为了解决这个问题,将当前单词转换为 RegExp,使用不区分大小写的搜索标志 (i),并使用 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)

【讨论】:

    【解决方案2】:

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

    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);

    【讨论】:

      猜你喜欢
      • 2021-12-10
      • 1970-01-01
      • 2019-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-26
      • 2018-10-25
      • 2019-11-20
      相关资源
      最近更新 更多