2

I have a class and want to work with it as Lists: e.g. List<int>, List<string>, ... , List<T> I have a class Randomizor which will take the collection data type that will be shuffled. How can I do so?

class Randomizor<T>
{
    public Randomizor()
    {

    }

    public Array Shuffle(Array toShuffle)
    {

    }
}

6 Answers6

3

Create a generic class like so:

class Randomizer<TList, TType> where TList : IList<TType>
{
    public TList Randomize(TList list)
    {
        // ...
    }
}

Or like so:

class Randomizer<T>
{
    public IList<T> Randomize(IList<T> list)
    {
        // ...
    }
}
Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443
  • Left to the OP. I think his question was about how to use generics in that case, not how to really implement the randomizing... – Daniel Hilgarth May 18 '11 at 13:35
2

Not very clear question... do you mean something like this?

public static class Randomizer<T>
{
   public static T GetRandom(List<T> list)
   {
      T value = default(T);
      // Perform some random logic.

      return value;
   }
}
Herman Cordes
  • 4,628
  • 9
  • 51
  • 87
1
class Randomizor<T>
{
    public Randomizor()
    {

    }

    public List<T> Shuffle(List<T> toShuffle)
    {

    }
}
Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443
Guillaume Davion
  • 434
  • 4
  • 12
1
class Randomizer<T>
{
    public Randomizer(ICollection<T> collection)
    {
        //Do something with collection using T as the type of the elements
    }            
}

However you may want to go for a generic extension method

static class Randomizer
{
    public static void Randomize<T>(this ICollection<T> collection)
    {
        //randomize the collection
    }
}

and the usage:

List<int> list = new List<int> { 1, 2, 3, 4, 5 };
list.Randomize();
Stilgar
  • 22,354
  • 14
  • 64
  • 101
  • Thank you. I have the following algorithm : have a list of int stores the available places. Put the content of a random index in the result collection. Delete the index from available places. How Can I return this result, please? –  May 18 '11 at 11:39
  • Well just make the method return a new collection instead of doing the shuffle in place (like my method signature suggests) – Stilgar May 18 '11 at 12:06
1

EDIT: I found two superior impementations after a little digging so I would suggest those in preference.

An extension method for this purpose and already been suggested previously here I include the code paraphrased to Shuffle below.

public static IEnumerable<T> Shuffle<T> (this IEnumerable<T> source)
{     
    Random random = new Random ();     
    T [] copy = source.ToArray ();      
    for (int i = copy.Length - 1; i >= 0; i--) 
    {         
        int index = random.Next (i + 1);
        yield return copy [index];
        copy [index] = copy [i];
    }
}

And an interesting solution adapted from this linq approach

public static IEnumerable<T> Shuffle<T> (this IEnumerable<T> source)
{     
    Random random = new Random ();     
    return source.OrderBy(i => Random.Next()).AsEnumerable();
}

The orignal answer but slower than the edits

public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> sequence) 
{     
    Random random = new Random();
    List<T> copy = sequence.ToList();
    while (copy.Count > 0)
    {
        int index = random.Next(copy.Count);
        yield return copy[index];
        copy.RemoveAt(index);
    }
} 

If you like one of these you should up vote the linked answer.

If you are very concerned about randomness, you could upgrade to one of the RNG algorithms from the Crypto API and seed it with some non deterministic value, like somthing generated from recent mouse activity. I suspect that would be overkill and it would degrade performance.

Community
  • 1
  • 1
Jodrell
  • 34,946
  • 5
  • 87
  • 124
  • As noted in the comments of the original answer this algorithm has higher complexity than needed because of the use of RemoveAt for a list. – Stilgar May 18 '11 at 12:09
-1

Maybe like this:

    public List<T> Shuffle<T>(List<T> toShuffle)
    {
        return toShuffle.OrderBy(x => Guid.NewGuid()).ToList();
    }

Or as an extension method

public static class Extensions
{
    public static List<T> Shuffle<T>(this List<T> toShuffle)
    {
        return toShuffle.OrderBy(x => Guid.NewGuid()).ToList();
    }
}
David
  • 8,340
  • 7
  • 49
  • 71
  • Probably because ordering by random does not yield even distribution? Let me downvote you too:) http://blogs.msdn.com/b/ericlippert/archive/2011/01/31/spot-the-defect-bad-comparisons-part-four.aspx – Stilgar May 18 '11 at 12:13
  • What part of the question even mentioned 'even distribution'? – David May 18 '11 at 12:16
  • OK but lets agree that an exception or infinite loop is not desired effect for any question on stack overflow even if it does not explicitly state that, shall we? :) – Stilgar May 18 '11 at 12:30
  • I have no problem if the code I provided is incorrect. But I can not see where it would cause an infinite loop – David May 18 '11 at 12:40
  • Did you read the article I linked in my comment because it explains why it can go in an infinite loop (though it probably won't)? – Stilgar May 18 '11 at 12:54
  • Did you read my code? It doesn't use the Sort method, it uses OrderBy, so even if Guid.NewGuid() did happen somehow to produce a duplicate it wouldn't matter. – David May 18 '11 at 13:07
  • Unless OrderBy documentation specifies that the selector function is called exactly once for each element and the result is somehow cached for use when a new comparison is required this implementation is wrong. Duplicates do not matter. What matters is that if X is compared to Y once and then it is compared to Y again the result should be the same. If your selector function is called several times it can produce inconsistent results. – Stilgar May 18 '11 at 14:02
  • So you now agree that the code I provided would not cause an infinite loop or an exception? Yes the selector function will produce inconsistent results, but all the OP ask for a list of its to be shuffled.. and that is what my code does. – David May 18 '11 at 14:16
  • No I don't agree. If the elements are let's say ints and the sorting algorithm used by OrderBy compares let's say 3 and 5 and it needs to compare it again (because sorting algorithms compare elements more than once) and your implementation (NewGuid()) returns a greater guid for 3 the first time and a greater guid for 5 the second time then the behaviour is undefined and the code can throw an exception or run infinitely. – Stilgar May 18 '11 at 14:23
  • An example of a valid sorting algorithm that can run practically infinitely is Bubble Sort (you know Bubble Sort, right?) What if the implementation raised a flag when a swap is done and checked this flag at the end of each iteration to see if the sorting is done. Then your "NewGuid()" comparison implementation would produce different guids every time and almost always there would be a swap more so if the list is large. However if your implementation did conform to the rule of every sorting algorithm that the comparison should be stable it would surely finish in at most N(O^2) time – Stilgar May 18 '11 at 14:29
  • If you look at the code for OrderedEnumerable you will see that the situation you describe should never occur as the provided key selector is evaluated for each element before the sort takes place. (and yes I have heard of a bubble sort once or twice) – David May 18 '11 at 15:00
  • @Dve can you guarantee that the implementation won't change in the next version of the framework? Relying on undocumented, non-pubic implementation details is skating on thin ice. – phoog May 18 '11 at 15:09
  • @Phoog by that rational we shouldn't be using .NET at all! – David May 18 '11 at 15:21
  • @Dve unless it is documented you should not depend on it but this is actually a valid argument (unlike your other arguments) if it was guaranteed by the documentation. I will take back my downvote because of it :) ... but my vote is locked for some amount of hours :( – Stilgar May 19 '11 at 06:34