Miguel Moura
Miguel Moura

Reputation: 39364

Shuffle list of strings consistently

Using C# 6 I have a list of names alphabetically ordered:

List<String> names = getAlphabeticallyOrderedNames();

I need to shuffle the names but I want to get the same result every time. So I cannot use:

List<String> shuffledNames = names.OrderBy(x => Guid.NewGuid());

I then tried something like:

List<String> shuffledNames = names.OrderBy(x => "d2fda3b5-4089-43f9-ba02-f68d138dee49");

Or

List<String> shuffledNames = names.OrderBy(x => Int32.MaxValue);

But the names are not shuffled ...

How can I solve this?

Upvotes: 2

Views: 2862

Answers (3)

Miguel Moura
Miguel Moura

Reputation: 39364

An Enumerable extension using Yield and having Seed value as parameter (Online Example):

public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Int32? seed = null) {

  List<T> buffer = source.ToList();

  Random random = seed.HasValue ? new Random(seed.Value) : new Random();

  Int32 count = buffer.Count;

  for (Int32 i = 0; i < count; i++) {          
    Int32 j = random.Next(i, count);
    yield return buffer[j];          
    buffer[j] = buffer[i];
  }

}

Upvotes: 1

Matthew Watson
Matthew Watson

Reputation: 109547

You can use a standard shuffle algorithm, such as the one from this answer:

Suitably modified to add a seed parameter, it would look like this:

public static void Shuffle<T>(IList<T> list, int seed)
{
    var rng = new Random(seed);
    int n = list.Count;

    while (n > 1)
    {
        n--;
        int k = rng.Next(n + 1);
        T value = list[k];
        list[k] = list[n];
        list[n] = value;
    }
}

Then to shuffle in a repeatable way, just specify the same seed for the shuffle for each repeated shuffle:

List<String> names = getAlphabeticallyOrderedNames();
int seed = 12345;
Shuffle(names, seed);

Upvotes: 5

Connell.O&#39;Donnell
Connell.O&#39;Donnell

Reputation: 3693

Try ordering by the hash value

var shuffled = names.OrderBy(n=>n.GetHashCode());

Upvotes: 0

Related Questions