Is there a way to use a foreach
loop to iterate through a collection backwards or in a completely random order?
Using System.Linq
you could do...
// List<...> list;
foreach (var i in list.Reverse())
{
}
For a random order you'd have to sort it randomly using list.OrderBy
(another Linq extension) and then iterate that ordered list.
var rnd = new Random();
var randomlyOrdered = list.OrderBy(i => rnd.Next());
foreach (var i in randomlyOrdered)
{
}
You could sort the List by supplying your own Comparator and iterate over that one.
I don't think there is a way to do so directly, but it's pretty much as good
to use an extension method that returns a new collection via the yield return
keyword. These could come from a pre-existing library; the others have pointed out that LINQ has a Reverse
method, and things like OrderBy
would also work.
Example: if you use the LINQ extension method Reverse()
on IEnumerable<T>
, which uses yield return
to give the collection in reverse order, then doing a foreach(var myThing in myCollection.Reverse())
will enumerate through the collection in reverse order.
Important: yield return
is key. It means "when I enumerate this collection, then go fetch things." As opposed to the alternative of just constructing a new, reversed collection, which is highly inefficient and possibly has side effects.
Do you want to rand a collection and interect with it?
If yes, try this:
Random rand = new Random(Environment.TickCount);
test.Sort((string v1, string v2) => {
if (v1.Equals(v2))
{
return 0;
}
int x = rand.Next();
int y = rand.Next();
if (x == y)
{
return 0;
}
else if (x > y)
{
return 1;
}
return -1;
});
for (string item in test)
{
Console.WriteLn(item);
}
// Note that test is List<string>;
As other answers mention, the Reverse() extension method will let you enumerate a sequence in reverse order.
Here's a random enumeration extension method:
public static IEnumerable<T> OrderRandomly<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);
}
}
Your usage would be:
foreach (int n in Enumerable.Range(1, 10).OrderRandomly())
Console.WriteLine(n);