对象数组的递归数组父匹配

时间:2019-08-03 22:37:25

标签: javascript arrays recursion

我想创建一个在递归数组循环中获取“父级”的函数,并生成那些“已用”父级的输出数组。

有点难以解释,但请看一下示例:

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']

要注意的是,EuropeBeNeLux)中有一个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
}

1 个答案:

答案 0 :(得分:3)

假定Africa对象位于顶层,则filter的顶层对象应通过其subRegions是否满足递归测试(该测试检查{ {1}}包括要迭代的对象的代码,或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);转换为Set(将selectedTerritories操作转换为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的方法来达到相同的结果,但是我认为这更清楚。

>