简体   繁体   中英

Randomizing part of array in C#

Lets say I have an array of integers. I found out that I can randomize the order of the elements simply by doing:

Random rnd = new Random();
array = array.OrderBy(x => rnd.Next()).ToArray();

But lets say I want to keep the first and the last elements in their original place. Can I do it using the same approach (using OrderBy()) or do I need to re-think my situation?

You can't do that in a single expression, but maybe a List<int> could help:

Random rnd = new Random();
var list = new List<int>();
list.Add(array[0]);
var partialArray = array.Skip(1).Take(array.Length - 2);
list.AddRange(partialArray.OrderBy(x => rnd.Next()));
list.Add(array[array.Length -1 ]);

Of course you can use the same approach, but you have to take care of the first and the last value. Just an example for your input array :

var list = array.Skip(1).Take(array.Length - 2).OrderBy(x => rnd.Next()).ToList();
list.Insert(0, array.First());
list.Add(array.Last());
array = list.ToArray();

Dmitry's example is basically the same, but gives you the option to keep more elements.

You can do it:

        int[] ints = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
        ints = ints.Select((x, index) => new { Value = x, Index = index })
               .OrderBy(tuple => (tuple.Index >= start && tuple.Index <= stop) ? random.Next(start, stop) : tuple.Index)
               .Select(tuple => tuple.Value)
               .ToArray();

You can just use a standard shuffle algorithm modified to use a range, for example (using the Fisher-Yates algorithm ):

public static void Shuffle<T>(IList<T> array, Random rng, int start, int end)
{
    for (int n = end+1; n > start+1;)
    {
        int k = rng.Next(start, n);
        --n;
        T temp = array[n];
        array[n] = array[k];
        array[k] = temp;
    }
}

Then call it like this:

Random rng = new Random();

for (int i = 0; i < 100; ++i)
{
    var array = Enumerable.Range(1, 12).ToArray();
    Shuffle(array, rng, 3, 9);
    Console.WriteLine(string.Join(", ", array));
}

A slightly different approach which doesn't involve using List....

        Random rnd = new Random();
        //array = array.OrderBy(x => rnd.Next()).ToArray();

        int lastIndexToChange = array.Length - 1;

        for (int i = 1; i < lastIndexToChange; i++)
        {
            var tempStore = array[i];
            int newPosition = rnd.Next(1, lastIndexToChange);

            array[i] = array[newPosition];
            array[newPosition] = tempStore;
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM