Как случайным образом перемешать массив в JavaScript?

У меня есть такой массив:

const myArray = ["яблоко", "банан", "вишня", "персик"];

Как я могу его перемешать? Я уже пробовал несколько способов, но они не всегда дают хороший результат. Какой самый эффективный метод для этого? Хотелось бы увидеть код с разъяснениями.

The Problem:

You want to shuffle a JavaScript array to randomize its element order. You’ve tried some methods, but they haven’t produced consistently good results, and you’re looking for the most efficient and reliable approach.

:gear: Step-by-Step Guide:

  1. Implement the Fisher-Yates Shuffle Algorithm: The Fisher-Yates (Knuth) shuffle algorithm is the most efficient and reliable way to shuffle an array in JavaScript, guaranteeing a uniform distribution of results. This algorithm iterates through the array from the end, swapping each element with a randomly chosen element from the remaining unshuffled portion.

    function shuffle(arr) {
        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]]; // Efficient swap using destructuring assignment
        }
        return arr;
    }
    
    const myArray = ["яблоко", "банан", "вишня", "персик"];
    const shuffledArray = shuffle(myArray);
    console.log(shuffledArray); // Output: The shuffled array
    
  2. Understand the Algorithm’s Logic: The algorithm starts from the last element of the array and iteratively swaps it with a randomly selected element from the elements before it. This ensures that every element has an equal chance of ending up in any position.

  3. Optional: Create a Copy to Preserve the Original: If you need to keep the original array unchanged, create a copy before shuffling:

    const myArray = ["яблоко", "банан", "вишня", "персик"];
    const shuffledArray = shuffle([...myArray]); // Creates a copy using the spread syntax
    console.log(myArray);      // Output: Original array (unchanged)
    console.log(shuffledArray); // Output: Shuffled array
    

:mag: Common Pitfalls & What to Check Next:

  • Avoid sort() with Math.random(): While seemingly simple, using myArray.sort(() => Math.random() - 0.5) is not a true random shuffle and can lead to biased results, especially with larger arrays. The Fisher-Yates algorithm provides a guaranteed uniform distribution.

  • Seed for Reproducibility (Advanced): If you need to reproduce the same shuffled order consistently (e.g., for testing), you can use a pseudo-random number generator with a seed value. Libraries like seedrandom provide this functionality.

  • Testing: Test your shuffling function thoroughly. For smaller arrays, you can visually inspect the output. For larger arrays, you might want to perform statistical tests to ensure the distribution is truly uniform.

:speech_balloon: Still running into issues? Share your (sanitized) config files, the exact command you ran, and any other relevant details. The community is here to help!

Я обычно копирую массив перед перемешиванием, чтоб не трогать оригинал:

const shuffled = [...myArray].sort(() => Math.random() - 0.5);

Математически не идеально, но для большинства задач норм. Быстро и читаемо. Если нужна точность - лучше Фишер-Йетс.

А какие способы ты уже пробовала? Хочется посмотреть, что не зашло. Фишер-Йетс обычно рулит для перемешивания - реально случайное распределение получается. А всякие сортировки с Math.random() часто криво работают, неравномерно получается.