工作中经常要处理列表打乱的问题,比如抽奖名单、测试数据顺序调整,或者给用户推荐内容时避免固定顺序。这时候用对随机排序方法就特别关键,不是简单点个“随机”按钮就行。
基础思路:Math.random() 配合 sort
最常见的做法是利用数组的 sort 方法结合 Math.random()。虽然简单,但有个坑——它并不真正随机。
const arr = [1, 2, 3, 4, 5];
arr.sort(() => Math.random() - 0.5);
// 结果看似随机,实则偏差大
这种方法因为排序算法本身的稳定性问题,会导致某些元素更容易出现在前面,长期使用会暴露规律。
真随机:Fisher-Yates 洗牌算法
想要真正公平打乱,得上 Fisher-Yates 算法。它的核心是从后往前遍历,每个位置和一个随机位置交换。
function shuffle(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}
const list = ['小王', '小李', '小张', '小刘'];
shuffle(list);
console.log(list); // 每次输出顺序完全不同且概率均等
这个方法在抽奖系统、游戏发牌逻辑里很常见,靠谱得多。
前端场景:Vue 或 React 中怎么用
比如你在做一个在线抽签组件,点击按钮就重新打乱名单。可以直接封装一个工具函数,在事件回调里调用 shuffle 并更新状态。
// React 示例
function RandomList() {
const [names, setNames] = useState(['一等奖', '谢谢参与', '再来一次']);
const handleShuffle = () => {
const shuffled = [...names].sort(() => Math.random() - 0.5); // 快速实现
setNames(shuffled);
};
return (
<div>
<ul>{names.map((name, i) => <li key={i}>{name}</li>)}</ul>
<button onClick={handleShuffle}>重新排序</button>
</div>
);
}
虽然这里用了简易写法,但如果涉及重要逻辑,建议替换成 Fisher-Yates 实现。
后端也能做:数据库随机取数
有时候不想把全部数据拉到前端再排,可以在查询时直接随机。MySQL 用 ORDER BY RAND() 就行。
SELECT * FROM users ORDER BY RAND() LIMIT 5;
不过数据量一大,性能就会明显下降。更好的方式是用主键范围随机采样,避免全表扫描。
实际应用中,选哪种方法得看场景。小数据快速展示,Math.random() 凑合用;追求公平性,比如抽奖、考试题顺序,必须上 Fisher-Yates;大数据集合,优先考虑后端支持的随机机制。