es6通过过滤对象数组过滤对象数组

时间:2018-12-11 18:45:06

标签: javascript filter

具有以下结构:

let filteredTasks = [
  {status: 'done', other: true},
  {status: 'nope', other: false},
  {status: 'done', other: true},
  {status: 'done', other: true},
  {status: 'done', other: false},
  {status: 'done', other: false},
  {status: 'started', other: false}
]

和:

let availableFilters = [{status: 'done'}, {other: false}]

如何过滤此数组以获得以下结果:

filteredTasks =
[{status: 'done', other: false}, {status: 'done', other: false}]

我的想法和尝试:

let filteredTasks = [
  {status: 'done', other: true},
  {status: 'nope', other: false},
  {status: 'done', other: true},
  {status: 'done', other: true},
  {status: 'done', other: false},
  {status: 'done', other: false},
  {status: 'started', other: false}
]

let availableFilters = [{status: 'done'}, {other: false}]

let filteredTasksList = availableFilters.map(item => {
    return runFilter(item)
})

function runFilter(currentFilter) {
  return filteredTasks.filter(item => {
    for (var key in currentFilter) {
        if (item[key] === undefined || item[key] !== currentFilter[key])
        return false
    }
    return true;
  })
}

...但是很明显,这遍及了每遍。

一如既往,我们非常感谢您提供反馈和帮助,因此在此先致谢。

编辑: 接受最初的评论作为适合我需要的解决方案。我用它来更进一步:

let filterTaskList = (list, filters) => {
  let entries = Object.entries(Object.assign(...filters))
  return list.filter(task => {
    return entries.every(([key, val]) => {
      return task[key] === val
     })
  })
}

2 个答案:

答案 0 :(得分:3)

您可以创建过滤器的单个对象,并获取用于过滤的条目。

let filteredTasks = [
  {status: 'done', other: true},
  {status: 'nope', other: false},
  {status: 'done', other: true},
  {status: 'done', other: true},
  {status: 'done', other: false},
  {status: 'done', other: false},
  {status: 'started', other: false}
],
 availableFilters = [{status: 'done'}, {other: false}], // your filters
  filters = Object.entries(Object.assign(...availableFilters)), // returns an array of the filter's own enumerable property
  result = filteredTasks.filter(o => filters.every(([k, v]) => o[k] === v)); // .every returns true, when every item is fulfilling the condition
  
console.log(result);
  

答案 1 :(得分:0)

代码优先:

let filteredTasks = [
  {status: 'done', other: true},
  {status: 'nope', other: false},
  {status: 'done', other: true},
  {status: 'done', other: true},
  {status: 'done', other: false},
  {status: 'done', other: false},
  {status: 'started', other: false}
]

let availableFilters = [{status: 'done'}, {other: false}]

const matchesFilter = (filter, item) => Object.entries(filter).every(([key, value]) => item[key] === value)

function withFilters (filters) {
  return item => filters.every(f => matchesFilter(f, item))
}

console.log(filteredTasks.filter(withFilters(availableFilters)))

说明:这里的两个有趣的功能是matchesFilterwithFilters

matchesFilter:获取一个对象filter,并将每个键/值与item进行比较以确保匹配。

withFilters接收一个过滤器列表,并返回一个可以与Array.prototype.filter一起使用以生成过滤器列表的函数。

然后,您只需使用withFilters(availableFilters)作为过滤器功能即可。您甚至可以保存该结果,以便以后再次使用。

let filterByAvailable = withFilters(availableFilters)
let availableTaks = filteredTasks.filter(filterByAvailable)