Không nên. Dùng array.sort(() => Math.random() - 0.5) là sai về mặt thống kê (không phân bố đều) và không ổn định trên một số engine.
Tại sao sort() random là sai?
- Thuật toán sort (Timsort, Quicksort) giả định comparator nhất quán (transitive). Random comparator vi phạm giả định này.
- Kết quả thiên vị: phần tử ở giữa mảng có xác suất di chuyển cao hơn.
- Chrome V8 từng có bug khiến sort không đổi chỗ gì với random comparator.
Thuật toán đúng: Fisher-Yates (Knuth Shuffle)
function shuffleArray(array) {
// Tạo bản sao nếu không muốn mutate original
const arr = [...array];
for (let i = arr.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[arr[i], arr[j]] = [arr[j], arr[i]]; // Destructuring swap
}
return arr;
}
// Dùng
const shuffled = shuffleArray([1,2,3,4,5,6,7,8,9]);
console.log(shuffled);
Giải thích Fisher-Yates
- Duyệt từ cuối về đầu (
i = n-1 ... 1). - Chọn index ngẫu nhiên
jtừ0đếni(bao gồmi). - Hoán đổi
arr[i]vàarr[j]. - Đảm bảo mọi hoán vị (permutation) có xác suất bằng nhau
1/n!.
Crypto-secure shuffle (cần bảo mật)
function secureShuffle(array) {
const arr = [...array];
const crypto = window.crypto || require('crypto').webcrypto;
for (let i = arr.length - 1; i > 0; i--) {
const randomBuffer = new Uint32Array(1);
crypto.getRandomValues(randomBuffer);
const j = randomBuffer[0] % (i + 1);
[arr[i], arr[j]] = [arr[j], arr[i]];
}
return arr;
}