基于JavaScript中过滤器数组的过滤器数组

时间:2019-02-14 11:12:25

标签: javascript ecmascript-6

我有一个用户数组和一个过滤器数组。

我需要根据过滤器数组过滤用户,但是当我这样做时,它将过滤一个数组,而不过滤其他数组

我的过滤器对象如下:

filters: {
  levels: [],
  locations: ['Laois'],
  subjects: ['Art']
}

我的用户如下:

const users = [
  {
    email: 'example1@gmail.com',
    levels: ['Ordinary'],
    location: 'Laois',
    subjects: ['Art', 'German']
  },
  {
    email: 'example2@gmail.com',
    levels: ['Higher', 'Ordinary'],
    location: 'Laois',
    subjects: ['English', 'German']
  }
]

基于上面的过滤器,过滤后的用户应该只能是一个,因为其中包含“艺术”和“劳埃斯”:

[{
    email: 'example1@gmail.com',
    levels: ['Ordinary'],
    location: 'Laois',
    subjects: ['Art', 'German']
  },
]

但是我仍然得到两个用户:

编辑 我的代码:

applyFilter = (visable) => {
    let { filters, users } = this.state;
    const { subjects, locations, levels } = filters;


    let filteredUsers = [];
    const filteredData = users.filter((user) =>
      user.subjects.some(subject => subjects.includes(subject)) ||
      locations.some(location => location === user.location) ||
      user.levels.some(level => levels.includes(level))
    );

    console.log(filteredData)


    if (!subjects.length && !locations.length && !levels.length) {
      filteredUsers = users;
    } else {
      filteredUsers = filteredData;
    }

    this.setState({
      filterModalVisible: visable,
      filteredResults: filteredUsers.length >= 0 ? filteredUsers : [],
    });
  }

5 个答案:

答案 0 :(得分:1)

您可以使用filterevery方法通过使用相同的键检查用户值中是否存在过滤器值中的每个元素来实现此目的。

const filters = {"levels":[],"locations":["Laois"],"subjects":["Art"]}
const users = [{"email":"example1@gmail.com","levels":["Ordinary"],"locations":"Laois","subjects":["Art","German"]},{"email":"example2@gmail.com","levels":["Higher","Ordinary"],"locations":"Laois","subjects":["English","German"]}]

const res = users.filter(user => {
  return Object.entries(filters)
    .every(([key, value]) => {
      if (Array.isArray(value)) {
        return value.every(filter => {
          return user[key] && user[key].includes(filter)
        })
      } else {
        return user[key] == value
      }
    })
})

console.log(res)

答案 1 :(得分:1)

您可以尝试使用filter()

const filters = {
  levels: [],
  locations: ['Laois'],
  subjects: ['Art']
}

const users = [
  {
    email: 'example1@gmail.com',
    levels: ['Ordinary'],
    location: 'Laois',
    subjects: ['Art', 'German']
  },
  {
    email: 'example2@gmail.com',
    levels: ['Higher', 'Ordinary'],
    location: 'Laois',
    subjects: ['English', 'German']
  }
]

var res = users.filter(info => info.location==filters.locations[0] && info.subjects.includes(filters.subjects[0]));

console.log(res);

答案 2 :(得分:1)

通过使用Array.filterArray.someArray.includes

,您可以为任何过滤器键提供通用解决方案。
  • 使用filter根据所有过滤条件验证每个条目
  • 如果过滤条件中有一个空列表,请继续检查下一个条件
  • 对于位置,由于filter keykey in object的区别是 ,因此请为我们检查位置的位置添加特定的检查包含在位置数组中
  • 对于其他字段,请检查过滤器值中是否存在数组中至少有1个条目。如果存在值,请继续检查下一个条件。
  • 条件检查后,请确认输入是否有效,如果没有中断则返回false

let filters = {levels: [],locations: ['Laois'],subjects: ['Art']};
let users = [{email: 'example1@gmail.com',levels: ['Ordinary'],location: 'Laois',subjects: ['Art', 'German']},{email: 'example2@gmail.com',levels: ['Higher', 'Ordinary'],location: 'Laois',subjects: ['English', 'German']}];

users = users.filter(v => {
  let response = true;
  for (let filter in filters) {
    if(!filters[filter].length) continue;
    if(filter === "locations") {
      response = response && filters.locations.includes(v.location)
    } else response = response && v[filter].some(f => filters[filter].includes(f));
    if(!response) break;
  }
  return response;
});
console.log(users);

答案 3 :(得分:0)

在过滤器内部使用过滤器

const filters = {
  levels: [],
  locations: ['Laois'],
  subjects: ['Art']
}

const users = [
  {
    email: 'example1@gmail.com',
    levels: ['Ordinary'],
    location: 'Laois',
    subjects: ['Art', 'German']
  },
  {
    email: 'example2@gmail.com',
    levels: ['Higher', 'Ordinary'],
    location: 'Laois',
    subjects: ['English', 'German']
  }
]
console.log(users.filter((e) => {
  var arr = e.subjects.filter((x) => filters.subjects.includes(x))
  if (arr.length > 0 && filters.locations.includes(e.location))
    return e
}))

答案 4 :(得分:0)

  1. 如果要匹配所有条件,则需要使用&&而不是||
  2. 根据您的要求,如果过滤器数组为空,则需要所有它们都匹配,因此您可以绕过该情况的检查

applyFilter = (visable) => {
    let { filters, users } = this.state;
    const { subjects, locations, levels } = filters;

    const filteredResults = users.filter((user) =>
        (!subjects.length || user.subjects.some(subject => subjects.includes(subject))) &&
        (!locations.length || locations.some(location => location === user.location)) &&
        (!levels.length || user.levels.some(level => levels.includes(level)))
    );

    this.setState({
        filterModalVisible: visable,
        filteredResults
    });
}