如何仅用循环实现动态变体数组的全排列组合?
问题:动态变体选项的全排列组合生成(仅循环实现)
需求:仅使用循环实现,处理动态的DataListVariant数组——每个元素包含nameVariant(变体名称)和对应的choiceVariant(该变体的选项数组),生成所有变体选项的全排列组合数组。要求支持:
- 变体数量动态变化(可新增/减少变体项)
- 每个变体的选项数量动态变化(选项数可多可少)
原始代码示例
let choiceVariant1 = ['Red','Blue'] let choiceVariant2 = ['Soft','Hard'] let choiceVariant3 = ['Polkadot','Square'] let choiceVariant4 = ['Metalic','Wood'] let DataListVariant = [{ nameVariant:'Color',choiceVariant:choiceVariant1 },{ nameVariant:'Texture',choiceVariant:choiceVariant2 },{ nameVariant:'Motive',choiceVariant:choiceVariant3 },{ nameVariant:'Material',choiceVariant:choiceVariant4 }]
目标输出示例
// 所有组合的数组,示例部分项: [ ['Red', 'Soft', 'Polkadot', 'Metalic'], ['Red', 'Soft', 'Polkadot', 'Wood'], // ... 中间省略所有组合 ['Blue', 'Hard', 'Square', 'Wood'] ]
动态场景示例
动态变体(新增变体项)
let choiceVariant5 = ['Small', 'Medium', 'Large'] let DataListVariant = [{ nameVariant:'Color',choiceVariant:choiceVariant1 },{ nameVariant:'Texture',choiceVariant:choiceVariant2 },{ nameVariant:'Motive',choiceVariant:choiceVariant3 },{ nameVariant:'Material',choiceVariant:choiceVariant4 },{ nameVariant:'Size',choiceVariant:choiceVariant5 }]
动态选项(单个变体的选项数变化)
// 某变体的选项数可任意增减 let choiceVariant = ['something1','something2','something3','something4', ...]
解决方案
核心思路
- 计算总组合数:所有变体的选项数相乘的结果
- 为每个变体计算权重值:权重 = 该变体之后所有变体的选项数乘积(用于确定当前变体在组合中的选项索引)
- 遍历每个组合位置(从0到总组合数-1),对每个变体,通过
(当前组合索引 / 权重) % 当前变体选项数得到该变体对应的选项索引,拼接出完整组合
代码实现(仅循环)
function generateAllVariants(DataListVariant) { // 预处理:提取选项数组并计算总组合数 const choiceLists = []; let totalCombinations = 1; for (let i = 0; i < DataListVariant.length; i++) { const choices = DataListVariant[i].choiceVariant; choiceLists.push(choices); totalCombinations *= choices.length; } // 计算每个变体的权重值 const weights = new Array(DataListVariant.length); weights[DataListVariant.length - 1] = 1; // 最后一个变体权重为1 for (let i = DataListVariant.length - 2; i >= 0; i--) { weights[i] = weights[i + 1] * choiceLists[i + 1].length; } // 遍历生成所有组合 const result = []; for (let comboIndex = 0; comboIndex < totalCombinations; comboIndex++) { const currentCombo = []; for (let variantIndex = 0; variantIndex < DataListVariant.length; variantIndex++) { const optionIndex = Math.floor(comboIndex / weights[variantIndex]) % choiceLists[variantIndex].length; currentCombo.push(choiceLists[variantIndex][optionIndex]); } result.push(currentCombo); } return result; } // 测试示例 let choiceVariant1 = ['Red','Blue'] let choiceVariant2 = ['Soft','Hard'] let choiceVariant3 = ['Polkadot','Square'] let choiceVariant4 = ['Metalic','Wood'] let DataListVariant = [{ nameVariant:'Color',choiceVariant:choiceVariant1 },{ nameVariant:'Texture',choiceVariant:choiceVariant2 },{ nameVariant:'Motive',choiceVariant:choiceVariant3 },{ nameVariant:'Material',choiceVariant:choiceVariant4 }] // 调用并打印结果 const allVariants = generateAllVariants(DataListVariant); allVariants.forEach((combo, index) => { console.log(`array ${index + 1} = [${combo.join(' , ')}]`); });
说明
- 完全通过循环实现,无递归调用
- 自动适配变体数量和每个变体的选项数变化:新增/删除变体、修改选项数时,无需修改核心逻辑
- 时间复杂度为O(N*M),其中N是总组合数,M是变体数量,性能高效
内容的提问来源于stack exchange,提问作者Jzx Naga
相关产品推荐
相关产品推荐

