Results 1 to 3 of 3

Thread: (.NET 3.5) Randomise a List of Items

  1. #1

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    (.NET 3.5) Randomise a List of Items

    VB version here.

    The following is an extension method for getting the contents of any IEnumerable(Of T) object, e.g. an array or List(Of T), in random order:
    Code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    public static class Enumerable
    {
        public static IEnumerable<T> Randomise<T>(this IEnumerable<T> items)
        {
            T[] result = null;
    
            if (items != null)
            {
                var rng = new Random();
    
                result = (from item in items
                          orderby rng.NextDouble()
                          select item).ToArray();
            }
    
            return result;
        }
    }
    Note that it obeys the rules for extension methods, i.e. it's a member of a static class and the first argument is declared with the 'this' keyword. You might use it something like this:
    Code:
    int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    
    foreach (var number in numbers.Randomise())
    {
        MessageBox.Show(number.ToString());
    }
    Try running that repeatedly and you'll get a different order each time.

    Note that you could write a regular method that does the same thing in earlier versions.

    EDIT: It's been brought to my attention that there is a significant issue with this code that, while unlikely to be encountered, could cause the operation to fail. Here's a reimplementation that isn't susceptible to this issue:
    csharp Code:
    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4.  
    5. public static class Enumerable
    6. {
    7.     public static IEnumerable<T> Randomise<T>(this IEnumerable<T> items)
    8.     {
    9.         T[] result = null;
    10.  
    11.         if (items != null)
    12.         {
    13.             var rng = new Random();
    14.  
    15.             result = items.ToArray();
    16.  
    17.             var keys = Array.ConvertAll(result, item => rng.NextDouble());
    18.  
    19.             Array.Sort(keys, result);
    20.         }
    21.  
    22.         return result;
    23.     }
    24. }
    Last edited by jmcilhinney; May 18th, 2017 at 01:13 AM. Reason: Simplified code

  2. #2

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: (.NET 3.5) Randomise a List of Items

    Note that I have simplified the code a little from the original. The new code will not throw an exception if you call it on a null reference but it will return a null reference. As such, an exception will be thrown if you try to enumerate the result, which did not happen with the old code. You could easily adjust the code to return an empty array if a null reference is passed in to avoid that if you think it's appropriate.

  3. #3
    Frenzied Member
    Join Date
    Jul 2008
    Location
    Rep of Ireland
    Posts
    1,380

    Re: (.NET 3.5) Randomise a List of Items

    Very nice use of extension methods jm!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width