如何在for循环中排除已使用的数组索引?附随机分组器代码
解决随机分组生成器中成员重复选中的问题
核心思路
不要每次随机抽取索引(容易重复),而是先将成员数组随机洗牌,再按顺序分配到各组,既能保证随机性,又能彻底避免重复选中同一成员。同时修正原代码中分组数量计算的逻辑错误。
修改后的关键代码
替换原createGroups函数,以下是修正后的完整代码:
function createGroups() { maxPeopleInGroup = parseInt(groupOptions.value); // 修正分组数计算:总人数 ÷ 每组最大人数,向上取整得到分组数 maxNumberGroups = Math.ceil(peopleArray.length / maxPeopleInGroup); let divWidth = 5 * maxPeopleInGroup; let divHeight = 7.5 * maxPeopleInGroup; // 清空旧分组并重置组号(避免多次点击后重复生成) outputMainDiv.innerHTML = ""; groupNumber = 1; // Fisher-Yates洗牌算法:生成随机顺序的成员副本(不修改原数组) const shuffledPeople = [...peopleArray]; for (let i = shuffledPeople.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [shuffledPeople[i], shuffledPeople[j]] = [shuffledPeople[j], shuffledPeople[i]]; } let currentIndex = 0; for (let i = 0; i < maxNumberGroups; i++) { let div = document.createElement("div"); div.setAttribute("id", `group${groupNumber}`); div.style.width = `${divWidth}vw`; div.style.height = `${divHeight}vh`; div.style.textAlign = "center"; div.style.alignItems = "center"; div.style.fontFamily = "Georgia, 'Times New Roman', Times, serif"; div.style.fontSize = "18pt"; div.style.fontWeight = "400"; div.style.border = "1px solid black"; outputMainDiv.appendChild(div); div.innerHTML = `Group ${groupNumber}:<br>`; // 按洗牌后的顺序分配成员,直到组满或所有成员分配完毕 for (let k = 0; k < maxPeopleInGroup && currentIndex < shuffledPeople.length; k++) { const person = shuffledPeople[currentIndex]; div.innerHTML += `${person.firstName} ${person.lastName} <br>`; currentIndex++; } groupNumber++; } }
关键修改说明
- 修正分组数计算:原代码中
maxNumberGroups的计算逻辑完全颠倒,现在改为用总人数除以每组人数并向上取整,确保所有成员都能分到组里。 - 洗牌算法:通过Fisher-Yates算法打乱成员顺序,保证分组的随机性,同时避免重复抽取的问题。
- 顺序分配:用
currentIndex跟踪当前分配到的成员位置,依次将洗牌后的成员放入各组,彻底杜绝重复。 - 重置分组状态:每次生成新分组前清空旧内容、重置组号,避免多次点击按钮后出现重复分组或组号递增的问题。
内容的提问来源于stack exchange,提问作者That New Coder
相关产品推荐
相关产品推荐

