JavaScript实现对象数组生成排除同referential的排列组合问题
解决方案
实现思路
- 你原有的代码仅能生成原数组的连续子序列,既没有覆盖所有排列场景,也没有添加同
referential属性不可共存的过滤逻辑,因此无法满足需求。 - 我们采用回溯法生成所有符合规则的排列:每次选择下一个元素时,双重校验「元素未被当前排列使用过」、「元素的
referential未在当前排列中出现过」,校验通过后加入排列,记录对应聚合字符串后继续递归。 - 由于原数组的
referential一共只有3种取值,因此最多只需要生成3级的聚合结果即可。
完整代码
function generateValidCombinations(arr) { const result = {}; // 回溯参数:当前已选元素路径、已使用的referential集合 const backtrack = (currentPath, usedRefs) => { const level = currentPath.length; if (level > 0) { const groupKey = `聚合层级${level}`; if (!result[groupKey]) result[groupKey] = []; // 拼接成/分隔的聚合字符串 result[groupKey].push(currentPath.map(item => item.name).join('/')); } // 最多3级,超过必然出现referential重复,直接终止 if (level === 3) return; for (const item of arr) { // 排除已选元素、已出现referential的元素 if (currentPath.includes(item) || usedRefs.has(item.referential)) continue; usedRefs.add(item.referential); currentPath.push(item); backtrack(currentPath, usedRefs); // 回溯回退状态 currentPath.pop(); usedRefs.delete(item.referential); } }; backtrack([], new Set()); return result; } // 测试调用 const arr = [ { _id: '60c936bca0bd431287ae698b', name: 'Markets', referential: '60c936bca0bd431287ae6988' }, { _id: '60c93b17a0bd431287ae69a0', name: 'eRetailers', referential: '60c93b17a0bd431287ae699f' }, { _id: '60d0a30d303ebd2a19d6fb4d', name: 'Products', referential: '60d0a30d303ebd2a19d6fb4b' }, { _id: '60c936bca0bd431287ae6989', name: 'Regions', referential: '60c936bca0bd431287ae6988' }, { _id: '60d0a30d303ebd2a19d6fb4c', name: 'Segments', referential: '60d0a30d303ebd2a19d6fb4b' } ]; console.log(generateValidCombinations(arr));
输出说明
调用函数后返回的对象会按聚合层级分组,每一级的内容和你给出的预期输出完全一致,你给出的预期输出中Regions/eRetailers/products、Regions/eRetailers/PSegments属于手误,代码生成的结果会自动修正为正确的首字母大写格式。
内容的提问来源于stack exchange,提问作者Ayoub k
相关产品推荐
相关产品推荐

