shapper said:
Hello,
How can I create a collection extension that orders its elements in a
random way? Something like:
public static class CollectionExtensions {
private static Random random = new Random();
public static T OrderRandom<T>(this IEnumerable<T> collection) {
T ordered = default(T);
Int32 count = 0;
foreach (T item in collection) {
// Random order elements?
}
return ordered;
} // Random
}
Can you clarify the question? The method you posted doesn't order the
elements. Rather, it returns a _single_ element, presumably one that
has been picked randomly.
If you really want a new ordering for the original collection, the
question remains: do you want to actually modify the original
collection? Or are you looking to simply have a differently-ordered
enumeration of the original collection?
If you just want the latter, one possible approach might look like this:
Random rnd = new Random();
var result = from r in
(from c in collection
select new { Item = c, Order = rnd.Next() })
orderby r.Order
select r.Item;
That will return a new order each time you enumerate the "result" query.
If you want to reorder it once, you'll have to resolve the query with
a call to "ToList()" and work from that.
An alternative approach would be to copy your collection into an array
and then shuffle the array. There have been several discussions in this
newsgroup discussing shuffle techniques. Just use Google Groups to
search the archives to learn more about that.
Shuffling would be somewhat more efficient than using LINQ (O(n) instead
of O(n log n)), but of course the code is somewhat more complicated and
easier to get wrong (it's particularly important, if you want a true
evenly-distributed randomized order, to exclude already-reordered
elements from subsequent iterations of the shuffle loop).
If you want to permanently reorder the original collection, you can use
either of the above techniques, but apply them directly to the original
collection. With LINQ, you'll have to copy the values back to the
original collection. With a shuffle, if the original collection is an
IList<T> or similar, you can just reorder in-place.
Pete