【问题标题】:Filtering an array: how to order the filters过滤数组:如何对过滤器进行排序
【发布时间】:2021-01-18 18:15:30
【问题描述】:

有两个组件:

  1. 设置状态的过滤器组件
  2. 基于过滤器呈现项目的输出组件

有2个数组:

  1. 所有项目的数组
  2. 所选过滤选项的数组。
    let itemsFiltered;
    if (this.state.continent !== "") { itemsFiltered = items.filter( (item) => item.continent == this.state.continent ); }
    if (this.state.country !== "") { itemsFiltered = items.filter( (item) => item.country == this.state.country ); }
    if (this.state.region !== "") { itemsFiltered = items.filter((item) => item.region == this.state.region); }
    if (this.state.activity !== "") { itemsFiltered = items.filter((item) => item.activity == this.state.activity); }
    if (this.state.skill !== "") { itemsFiltered = items.filter((item) => item.skill == this.state.skill); }

问题:它不适用于技能和区域。对于技能,如果首先选择它,它就会起作用,但如果已经做出了其他选择,它就不起作用。对于地区,它根本不应用过滤器。因此,它仅显示独立于过滤器集的所有项目。它适用于所有其他过滤器及其组合。

这是数据的样子(虚拟):

{
    title: "Item 1",
    description: "Description of the item",
    image: imageItem1,
    continent: "europe",
    country: "portugal",
    region: "norte",
    activity: "kite",
    skill: "proLocal",
},

您将如何编写它以使其工作?过滤器应该以不同的方式排序还是我缺少其他方法?

扩展(下面的 cmets 代码):尝试通过过滤器进行迭代失败,因为您无法通过状态对象进行迭代:

    let itemsFiltered = items.slice();
    const filtersSet = ["continent", "country", "region", "activity", "skill"]
    for (let i = 0; i < filtersSet.length; i++) {
      if (this.state.filtersSet[i] !== "") {itemsFiltered = itemsFiltered.filter( item => item.filtersSet[i] == this.state.filtersSet[i] );}
    }

【问题讨论】:

  • 看来您必须将过滤后的项目从前一个过滤器传递到下一个过滤器,如下所示:let itemsFiltered = items; if(...) itemsFiltered = itemsFiltered.filter(...)

标签: javascript arrays reactjs


【解决方案1】:

问题

似乎不应该使用多个过滤器进行过滤,因为每个过滤器操作都会完全覆盖任何先前的过滤结果。

let itemsFiltered;
if (this.state.continent !== "") {
  itemsFiltered = items.filter(
    (item) => item.continent == this.state.continent
  );
}
if (this.state.country !== "") {
  itemsFiltered = items.filter((item) => item.country == this.state.country);
}
if (this.state.region !== "") {
  itemsFiltered = items.filter((item) => item.region == this.state.region);
}
if (this.state.activity !== "") {
  itemsFiltered = items.filter((item) => item.activity == this.state.activity);
}
if (this.state.skill !== "") {
  itemsFiltered = items.filter((item) => item.skill == this.state.skill);
}

解决方案

您可以从前一个过滤器操作的结果中过滤每个后续过滤器。

let itemsFiltered = items.slice();
if (this.state.continent !== "") {
  itemsFiltered = itemsFiltered.filter(item => item.continent === this.state.continent);
}
if (this.state.country !== "") {
  itemsFiltered = itemsFiltered.filter(item => item.country === this.state.country);
}
if (this.state.region !== "") {
  itemsFiltered = itemsFiltered.filter(item => item.region === this.state.region);
}
if (this.state.activity !== "") {
  itemsFiltered = itemsFiltered.filter(item => item.activity === this.state.activity);
}
if (this.state.skill !== "") {
  itemsFiltered = itemsFiltered.filter(item => item.skill == this.state.skill);
}

或者为了节省大量的数组迭代,在一个过滤器函数中完成所有操作。

const itemsFiltered = items.filter((item) => {
  if (this.state.continent) return item.continent === this.state.continent;
  if (this.state.country) return item.country === this.state.country;
  if (this.state.region) return item.region === this.state.region;
  if (this.state.activity) return item.activity === this.state.activity;
  if (this.state.skill) return item.skill === this.state.skill;
  return true;
});

【讨论】:

  • 谢谢,当然,这绝对有道理。您的第一个解决方案有效。第二种解决方案(“在单个过滤器功能中”)不起作用。或者,我尝试使用 for 循环,但这也不起作用。它不允许像这样遍历状态对象: let itemsFiltered = items.slice(); const filtersSet = ["continent", "country", "region", "activity", "skill"] for (let i = 0; i item.filtersSet[i] == this.state.filtersSet[i] );} }
猜你喜欢
  • 2015-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-28
  • 1970-01-01
  • 1970-01-01
  • 2013-08-16
  • 1970-01-01
相关资源
最近更新 更多