Randomize arrays in C#

This example builds a Randomizer class that lets you randomize arrays. It provides a generic Randomize method that randomizes an array containing any kind of data. The following code shows the class.

public class Randomizer
{
    public static void Randomize<T>(T[] items)
    {
        Random rand = new Random();

        // For each spot in the array, pick
        // a random item to swap into that spot.
        for (int i = 0; i < items.Length - 1; i++)
        {
            int j = rand.Next(i, items.Length);
            T temp = items[i];
            items[i] = items[j];
            items[j] = temp;
        }
    }
}

The Randomize method is static so you can invoke it without creating an instance of the class.

The method first creates a Random object. Then for each position i in the array (except the last position), the code picks a random item between position i and the end of the array. It then swaps the selected item into position i. When it is finished, the array is randomized.

Note that this is the easiest way to pick several random items from the array without duplication. To pick one item, you can simply use a Random object to pick an item. To pick several items, it’s easiest to randomize the whole array and then just use the first several items.

Analysis

To see why this method randomizes the values uniformly, think about a value m somewhere in the array containing N items. We pick any random entry on the first pick so, assuming the random number generator is fair, there’s a 1/N chance that m is picked on the first try for the first slot. Once placed, numbers are not moved, so there’s a 1/N chance that m lands in the first slot.

There’s a (N-1)/N chance that m isn’t chosen for the first slot. When considering the second slot, we’re picking out of only N – 1 items so there’s a 1/(N-1) chance that we pick m for the second slot. Multiplying by the chance that it didn’t land in the first slot already, we get a [(N-1)/N] * [1/(N-1)] = 1/N chance overall that it lands in the second slot.

Third slot? (N-1)/N * (N-2)/(N-1) * 1/(N-2) = 1/N. And so forth.

This shows there’s a 1/N chance thaht any value m will end up in any particular position in the randomized array.

Using Randomize

The following code shows how the main program uses the Randomize method.

private void Randomize_Click(object sender, EventArgs e)
{
    // Put the items in an array.
    string[] items = txtItems.Lines;

    // Randomize.
    Randomizer.Randomize(items);

    // Display the result.
    txtResult.Lines = items;
    txtResult.Select(0, 0);
}

This code gets the lines of text in the txtItems TextBox and stores them in the items array. It calls Randomizer.Randomize to randomize the array, and then sets the TextBox‘s Lines property to the randomized strings.

(Note that the program could use the statement Randomizer.Randomize<string>(items); to randomize the array. This version explicitly tells the program that it wants to use the generic version of the method that works with the string data type. However, the compiler is smart enough to figure out that this is the version the program wants to use so you don’t need to include the generic type parameter if you don’t want to.)






This entry was posted in algorithms, mathematics and tagged , , , , , , , , , , . Bookmark the permalink.

7 Responses to Randomize arrays in C#

  1. Pingback: Make random groups of people or other objects in C# |

  2. Pingback: Make random groups of people or other objects in C# |

  3. Pingback: Make extension methods that randomize arrays and listsC# Helper

  4. Ello says:

    I know boxing occurs in this code being that listbox takes object but if you have a small amount, have the correct type, or different datatype this code is just as effective.

    static Random r = new Random();
    private void button1_Click_1(object sender, EventArgs e)
    {
        listBox2.Items.Clear();
        List items = new List();
        foreach (var item in listBox1.Items)
        {
            items.Add((string)item);
        }
    
        var randomItemList = from i in items
                             orderby r.Next()
                             select i;
    
        foreach (var item in randomItemList)
        {
            listBox2.Items.Add(item);
        }
    }

    With arrays you could use the AsEnumerable method.

  5. Ello says:

    For the next post when you want to take random group you could use Enumerable.Take function 🙂 cheers

    • RodStephens says:

      True. You can also modify the Randomize method so it only randomizes part of the array. For example, if you want to pick 5 items from an array containing 1 million, you only need to repeat the loop 5 times. Then you can use Enumerable.Take to grab the first 5 values. 😉

Leave a Reply

Your email address will not be published. Required fields are marked *