如何实现点击时从数组中随机展示唯一对象?
实现随机展示数组中唯一对象的方案
要解决随机展示不重复对象的问题,核心是跟踪已选中的索引,确保每次选的都是未出现过的,直到所有元素轮完再重新开始。下面提供两种可行的实现方式:
方案一:维护剩余未选中索引列表
通过一个状态数组记录还没被选过的索引,每次从里面随机挑一个,挑完就移除,空了再重置。
import { useState, useEffect } from 'react'; // 假设你的目标数组是array function YourComponent() { const [index, setIndex] = useState(null); // 存储剩余未被选中的索引 const [remainingIndexes, setRemainingIndexes] = useState([]); // 初始化剩余索引列表 useEffect(() => { setRemainingIndexes([...Array(array.length).keys()]); }, [array.length]); const randomScenario = () => { // 如果所有索引都选过了,重置列表 if (remainingIndexes.length === 0) { setRemainingIndexes([...Array(array.length).keys()]); } // 从剩余索引里随机选一个 const randomPos = Math.floor(Math.random() * remainingIndexes.length); const selectedIndex = remainingIndexes[randomPos]; // 更新剩余索引,移除刚选中的那个 setRemainingIndexes(prev => prev.filter((_, idx) => idx !== randomPos)); setIndex(selectedIndex); }; return ( <div> {index !== null && <div>{JSON.stringify(array[index])}</div>} <button onClick={randomScenario}>随机展示唯一对象</button> </div> ); }
方案二:Fisher-Yates洗牌后顺序取
先把数组的索引用公平的洗牌算法打乱,然后依次取出索引,取完一轮后重新洗牌,实现不重复的随机效果。
import { useState, useEffect } from 'react'; function YourComponent() { const [index, setIndex] = useState(null); // 存储打乱后的索引数组 const [shuffledIndexes, setShuffledIndexes] = useState([]); // 当前取到的位置 const [currentPos, setCurrentPos] = useState(0); // 初始化时洗牌索引数组 useEffect(() => { shuffleIndexes(); }, [array.length]); // Fisher-Yates洗牌算法,保证打乱的公平性 const shuffleIndexes = () => { const indexes = [...Array(array.length).keys()]; for (let i = indexes.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [indexes[i], indexes[j]] = [indexes[j], indexes[i]]; } setShuffledIndexes(indexes); setCurrentPos(0); }; const randomScenario = () => { // 一轮取完,重新洗牌 if (currentPos >= shuffledIndexes.length) { shuffleIndexes(); return; } const selectedIndex = shuffledIndexes[currentPos]; setIndex(selectedIndex); setCurrentPos(prev => prev + 1); }; return ( <div> {index !== null && <div>{JSON.stringify(array[index])}</div>} <button onClick={randomScenario}>随机展示唯一对象</button> </div> ); }
说明
- 两种方案都能保证每次展示的对象不重复,直到所有元素都轮过一遍才会循环。
- 如果你的数组长度会动态变化,两个方案里的
useEffect都通过array.length作为依赖,会自动重新初始化索引列表/洗牌数组。
内容的提问来源于stack exchange,提问作者Elhassan Abdelhafez
相关产品推荐
相关产品推荐

