Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> JavaScript

วิธีสุ่มลำดับ Array ใน JavaScript (Shuffle Array)

อัลกอริทึม Fisher-Yates (Knuth Shuffle)

วิธีมาตรฐานในการสุ่มลำดับ Array ให้ได้การกระจายที่เท่าเทียม (Uniform Distribution) คือ Fisher-Yates Shuffle

ตัวอย่างโค้ด

<html>
<body>
  <script>
    function randomFunc(myArr) {
      var l = myArr.length, temp, index;
      while (l > 0) {
        index = Math.floor(Math.random() * l);
        l--;
        temp = myArr[l];
        myArr[l] = myArr[index];
        myArr[index] = temp;
      }
      return myArr;
    }
    
    var arr = [10, 20, 30, 40, 50];
    document.write(randomFunc(arr));
  </script>
</body>
</html>

ผลลัพธ์ตัวอย่าง

20,50,40,30,10

หมายเหตุ: ผลลัพธ์จะต่างกันทุกครั้งที่รัน

คำอธิบายอัลกอริทึม

  1. เริ่มจาก index สุดท้าย (l = length - 1)
  2. สุ่ม index ระหว่าง 0 ถึง l (Inclusive)
  3. สลับค่าระหว่าง myArr[l] และ myArr[index]
  4. ลด l ลง 1 ทำซ้ำจน l = 0

เวอร์ชัน ES6+ แบบสั้น (Immutable - ไม่เปลี่ยน Array ต้นฉบับ)

function shuffle(array) {
  return [...array].sort(() => Math.random() - 0.5);
}
// หมายเหตุ: sort() แบบนี้ไม่ได้ Uniform Distribution จริง แต่ใช้ได้สำหรับงานเบาๆ

// Fisher-Yates แบบ Immutable
function shuffleImmutable(array) {
  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]];
  }
  return arr;
}

ตัวอย่างการใช้งานจริง

// สุ่มการ์ด
const deck = [...Array(52)].map((_, i) => i);
const shuffled = shuffleImmutable(deck);

// สุ่มผู้ชนะ
const participants = ['Alice', 'Bob', 'Charlie', 'David'];
const winner = shuffleImmutable(participants)[0];

// สุ่มลำดับเพลง
const playlist = ['song1.mp3', 'song2.mp3', 'song3.mp3'];
player.playlist = shuffleImmutable(playlist);

ข้อควรระวัง

  • array.sort(() => Math.random() - 0.5) ไม่ได้เป็น Uniform Shuffle เนื่องจาก Sort Algorithm ไม่ได้ออกแบบมาเพื่อสุ่ม
  • Fisher-Yates ให้ผลลัพธ์ Uniform จริงๆ และมี Performance ดี (O(n))
  • ฟังก์ชันตัวอย่าง randomFunc แบบเดิม เปลี่ยน Array ต้นฉบับ (Mutate) ควรสร้าง Copy ก่อนถ้าต้องการเก็บต้นฉบับ