原生JS中如何避免for循环重复使用数组索引?
解决随机分组生成器的重复索引问题
下面是几种实用方案,彻底避免同一索引重复被选中:
方法一:用集合跟踪已使用的索引
每次生成随机索引后,先检查是否已在已选集合中,若重复则重新生成,直到拿到未使用的索引。逻辑直观,适合小规模数据场景。
示例代码:
const people = ["张三", "李四", "王五", "赵六", "孙七"]; const usedIndexes = new Set(); const groupSize = 2; const groups = []; while (usedIndexes.size < people.length) { let randomIndex; // 循环获取未使用的索引 do { randomIndex = Math.floor(Math.random() * people.length); } while (usedIndexes.has(randomIndex)); usedIndexes.add(randomIndex); // 填充分组,组满则新建 const currentGroup = groups[groups.length - 1]; if (!currentGroup || currentGroup.length === groupSize) { groups.push([people[randomIndex]]); } else { currentGroup.push(people[randomIndex]); } } console.log(groups);
方法二:Fisher-Yates洗牌算法(推荐)
先将原数组随机打乱,再按分组大小分割数组。这种方法无需反复生成随机数,每个元素仅被处理一次,从根源上杜绝重复问题,效率更高。
示例代码:
const people = ["张三", "李四", "王五", "赵六", "孙七"]; const groupSize = 2; // Fisher-Yates洗牌函数 function shuffleArray(arr) { const newArr = [...arr]; for (let i = newArr.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [newArr[i], newArr[j]] = [newArr[j], newArr[i]]; } return newArr; } // 洗牌后分割为分组 const shuffledPeople = shuffleArray(people); const groups = []; for (let i = 0; i < shuffledPeople.length; i += groupSize) { groups.push(shuffledPeople.slice(i, i + groupSize)); } console.log(groups);
方法三:移除已选中的元素
每次选中元素后,从原数组的副本中删除该元素,后续随机索引的范围会自动缩小,不会再选中已用元素。注意不要直接修改原数组,建议先复制一份操作。
示例代码:
const people = ["张三", "李四", "王五", "赵六", "孙七"]; const groupSize = 2; const peopleCopy = [...people]; const groups = []; while (peopleCopy.length > 0) { const randomIndex = Math.floor(Math.random() * peopleCopy.length); const person = peopleCopy.splice(randomIndex, 1)[0]; const currentGroup = groups[groups.length - 1]; if (!currentGroup || currentGroup.length === groupSize) { groups.push([person]); } else { currentGroup.push(person); } } console.log(groups);
内容的提问来源于stack exchange,提问作者That New Coder
相关产品推荐
相关产品推荐

