我想创建一个在递归数组循环中获取“父级”的函数,并生成那些“已用”父级的输出数组。
有点难以解释,但请看一下示例:
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
}
答案 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
的方法来达到相同的结果,但是我认为这更清楚。