【问题标题】:Recursive array parent match from array of objects来自对象数组的递归数组父匹配
【发布时间】:2019-08-04 08:27:28
【问题描述】:

我想创建一个在递归数组循环中获取“父级”的函数,并为这些“使用过的”父级创建一个输出数组。

解释起来有点难,看一下例子:

const regions = [{
  name: 'Europe',
  subRegions: [{
    name: 'BeNeLux',
    territories: [{
      code: 'NL',
      name: 'Netherlands'
    }, {
      code: 'DE',
      name: 'Germany'
    }, {
      code: 'LU',
      name: 'Luxembourg'
    }]
  }],
  territories: [{
    code: 'UK',
    name: 'United Kingdom'
  }, {
    code: 'AL',
    name: 'Albania'
  }, {
    code: 'ZW',
    name: 'Switzerland'
  }]
}, {
  name: 'Africa',
  territories: [{
    code: 'GH',
    name: 'Ghana'
  }]
}]

const selectedTerritories = ['NL', 'UK', 'GH']

此时我需要一个函数,通过代码搜索一个地区的所有 TOP 区域,因此输出如下所示:

const activeRegions = ['Europe', 'Africa']

需要注意的是,Europe (BeNeLux) 中有一个 subRegion,并且递归到了那个点,它不应该返回 BeNeLux 作为活动区域,而是返回 Europe

这是我尝试过的,但子区域名称重复,它忽略了“父”递归发现要求:

const getRegionsLabelFromTerritoryList = (activeTerritories, regions, activeRegions = []) => {
  regions.forEach((region) => {
    if (region.territories) {
      region.territories.forEach(t => {
        if (activeTerritories.includes(t.code)) {
          activeRegions.push(region)
        }
      })
    }

    if (region.subRegions) {
      getRegionsLabelFromTerritoryList(region.subRegions, activeRegions)
    }
  })

  return activeRegions
}

【问题讨论】:

  • 这看起来不再需要递归。我再也看不到递归子结构了。
  • @PatrickRoberts 嗯,我觉得它应该递归解决,因为在 subRegionregions 中可以有无限的深度。
  • 您确定输入结构是您发布的方式吗?现在,顶级regions 数组包含一个对象(欧洲),和一个数组(一个包含非洲的数组),这似乎很不寻常。 Africa 对象是否应该位于外部数组的顶层?
  • @CertainPerformance 糟糕,这里已经很晚了......已修复

标签: javascript arrays recursion


【解决方案1】:

假设Africa对象应该在顶层,filter顶层对象通过其subRegions是否满足递归测试(检查selectedTerritories是否包含代码被迭代的对象,或者是否有任何subRegions 孩子通过了测试):

const regions = [{
  name: 'Europe',
  subRegions: [{
    name: 'BeNeLux',
    territories: [{
      code: 'NL',
      name: 'Netherlands'
    }, {
      code: 'DE',
      name: 'Germany'
    }, {
      code: 'LU',
      name: 'Luxembourg'
    }]
  }],
  territories: [{
    code: 'UK',
    name: 'United Kingdom'
  }, {
    code: 'AL',
    name: 'Albania'
  }, {
    code: 'ZW',
    name: 'Switzerland'
  }]
}, {
  name: 'Africa',
  territories: [{
    code: 'GH',
    name: 'Ghana'
  }]
}];

const selectedTerritories = ['NL', 'UK', 'GH'];

const regionPasses = ({ subRegions, territories }) => (
  territories.some(({ code }) => selectedTerritories.includes(code))
  || (subRegions && subRegions.some(regionPasses))
);
    
const topSelected = regions
  .filter(regionPasses)
  .map(({ name }) => name);
console.log(topSelected);

为了减少计算复杂度,您可以先将 selectedTerritories 转换为 Set(将 O(n) 操作转换为 O(1) 操作):

const regions = [{
  name: 'Europe',
  subRegions: [{
    name: 'BeNeLux',
    territories: [{
      code: 'NL',
      name: 'Netherlands'
    }, {
      code: 'DE',
      name: 'Germany'
    }, {
      code: 'LU',
      name: 'Luxembourg'
    }]
  }],
  territories: [{
    code: 'UK',
    name: 'United Kingdom'
  }, {
    code: 'AL',
    name: 'Albania'
  }, {
    code: 'ZW',
    name: 'Switzerland'
  }]
}, {
  name: 'Africa',
  territories: [{
    code: 'GH',
    name: 'Ghana'
  }]
}];

const selectedTerritories = new Set(['NL', 'UK', 'GH']);

const regionPasses = ({ subRegions, territories }) => (
  territories.some(({ code }) => selectedTerritories.has(code))
  || (subRegions && subRegions.some(regionPasses))
);
    
const topSelected = regions
  .filter(regionPasses)
  .map(({ name }) => name);
console.log(topSelected);

您可以使用单个外部循环而不是两个(.reduce 或其他东西而不是 .filter 后跟 .map)来实现相同的结果,但我认为这更清楚。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-02
  • 1970-01-01
  • 2020-08-04
  • 2016-11-03
  • 2011-06-14
  • 1970-01-01
相关资源
最近更新 更多