Can you enumerate a collection in C# out of order?

前端 未结 11 2047
天涯浪人
天涯浪人 2020-12-17 17:15

Is there a way to use a foreach loop to iterate through a collection backwards or in a completely random order?

相关标签:
11条回答
  • 2020-12-17 18:02

    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)
    {
    }
    
    0 讨论(0)
  • 2020-12-17 18:02

    You could sort the List by supplying your own Comparator and iterate over that one.

    0 讨论(0)
  • 2020-12-17 18:04

    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.

    0 讨论(0)
  • 2020-12-17 18:06

    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>;
    
    0 讨论(0)
  • 2020-12-17 18:09

    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);
    
    0 讨论(0)
提交回复
热议问题