首页 > 解决方案 > 我正在根据字符串数组过滤数组元素,但是,我正在将字符串数组转换为对象数组。我需要另一个循环吗?

问题描述

我有一个元素数组,其中每个元素都是来自某个游戏的卡片,并且我成功地根据另一个数组过滤卡片,如下所示:

let regions = ['Noxus', 'Demacia', 'Shadow Isles', 'Freljord', 'Ionia', 'Piltover & Zaun']

filteredByRegion(cards){
    return cards.filter((card) => {
        return this.regions.includes(card.region)
    })
}

但是,现在我试图将字符串数组转换为对象数组,其中字符串将只是对象的属性之一。

let regions = [
    { name: "Noxus", active: true },
    { name: "Demacia", active: true },
    { name: "Shadow Isles", active: false },
    { name: "Freljord", active: true },
    { name: "Ionia", active: true },
    { name: "Piltover & Zaun", active: false },
]

现在我只想从active属性设置为true. 这意味着我需要在进行卡片过滤之前获取所有活动区域。所以我把函数改成这样:

filteredByRegion(cards){
    let activeRegions = regions.filter((region) => {
        return region.active === true
    })

    return cards.filter((card) => {
        return this.regions.includes(card.region)
    })
}

现在我有点困惑如何更改它,cards.filter()以便它只返回其区域属性与我的activeRegions变量中的一个活动区域匹配的卡片。我是否需要卡片过滤器内的 for 循环来循环每个活动区域并将返回放置this.regions.includes(card.region)在该循环中?

标签: javascript

解决方案


首先通过过滤和映射regions对象数组来创建活动区域的集合(或数组)。然后,您可以创建另一个this.regions包含在这些活动区域中的 Set。最后,根据cards参数是否包含在该 Set 中来过滤参数:

filteredByRegion(cards){
  const activeRegionsSet = new Set(
    regions
      .filter(({ active }) => active)
      .map(({ name }) => name)
  );
  const theseActiveRegions = new Set(this.regions.filter(region => activeRegionsSet.has(region)));
  return cards.filter(card => theseActiveRegions.has(card.region));
}

或者,如果您不喜欢解构:

filteredByRegion(cards){
  const activeRegionsSet = new Set(
    regions
      .filter(obj => obj.active)
      .map(obj => obj.name)
  );
  const theseActiveRegions = new Set(this.regions.filter(region => activeRegionsSet.has(region)));
  return cards.filter(card => theseActiveRegions.has(card.region));
}

集合是为了降低计算复杂度(Set#hasO(1),而是Array#includesO(n)。但是,如果您对数组更熟悉,相同的代码将如下所示:

filteredByRegion(cards){
  const activeRegions = regions
    .filter(({ active }) => active)
    .map(({ name }) => name);
  const theseActiveRegions = this.regions.filter(region => activeRegions.includes(region));
  return cards.filter(card => theseActiveRegions.includes(card.region));
}

这无关紧要,但是您可以regions通过推入条件测试中仅迭代原始数组一次而不是两次,尽管它的功能较少:

const activeRegions = [];
for (const { active, name } of regions) {
  if (active) {
    activeRegions.push(name);
  }
}

推荐阅读