How do you get the index of the current iteration of a foreach loop?

后端 未结 30 1683
刺人心
刺人心 2020-11-22 07:05

Is there some rare language construct I haven\'t encountered (like the few I\'ve learned recently, some on Stack Overflow) in C# to get a value representing the current iter

相关标签:
30条回答
  • 2020-11-22 07:24

    Finally C#7 has a decent syntax for getting an index inside of a foreach loop (i. e. tuples):

    foreach (var (item, index) in collection.WithIndex())
    {
        Debug.WriteLine($"{index}: {item}");
    }
    

    A little extension method would be needed:

    public static IEnumerable<(T item, int index)> WithIndex<T>(this IEnumerable<T> self)       
       => self.Select((item, index) => (item, index)); 
    
    0 讨论(0)
  • 2020-11-22 07:25

    My solution for this problem is an extension method WithIndex(),

    http://code.google.com/p/ub-dotnet-utilities/source/browse/trunk/Src/Utilities/Extensions/EnumerableExtensions.cs

    Use it like

    var list = new List<int> { 1, 2, 3, 4, 5, 6 };    
    
    var odd = list.WithIndex().Where(i => (i.Item & 1) == 1);
    CollectionAssert.AreEqual(new[] { 0, 2, 4 }, odd.Select(i => i.Index));
    CollectionAssert.AreEqual(new[] { 1, 3, 5 }, odd.Select(i => i.Item));
    
    0 讨论(0)
  • 2020-11-22 07:25

    I don't think this should be quite efficient, but it works:

    @foreach (var banner in Model.MainBanners) {
        @Model.MainBanners.IndexOf(banner)
    }
    
    0 讨论(0)
  • 2020-11-22 07:28

    You could wrap the original enumerator with another that does contain the index information.

    foreach (var item in ForEachHelper.WithIndex(collection))
    {
        Console.Write("Index=" + item.Index);
        Console.Write(";Value= " + item.Value);
        Console.Write(";IsLast=" + item.IsLast);
        Console.WriteLine();
    }
    

    Here is the code for the ForEachHelper class.

    public static class ForEachHelper
    {
        public sealed class Item<T>
        {
            public int Index { get; set; }
            public T Value { get; set; }
            public bool IsLast { get; set; }
        }
    
        public static IEnumerable<Item<T>> WithIndex<T>(IEnumerable<T> enumerable)
        {
            Item<T> item = null;
            foreach (T value in enumerable)
            {
                Item<T> next = new Item<T>();
                next.Index = 0;
                next.Value = value;
                next.IsLast = false;
                if (item != null)
                {
                    next.Index = item.Index + 1;
                    yield return item;
                }
                item = next;
            }
            if (item != null)
            {
                item.IsLast = true;
                yield return item;
            }            
        }
    }
    
    0 讨论(0)
  • 2020-11-22 07:30
    int index;
    foreach (Object o in collection)
    {
        index = collection.indexOf(o);
    }
    

    This would work for collections supporting IList.

    0 讨论(0)
  • 2020-11-22 07:32

    I just had this problem, but thinking around the problem in my case gave the best solution, unrelated to the expected solution.

    It could be quite a common case, basically, I'm reading from one source list and creating objects based on them in a destination list, however, I have to check whether the source items are valid first and want to return the row of any error. At first-glance, I want to get the index into the enumerator of the object at the Current property, however, as I am copying these elements, I implicitly know the current index anyway from the current destination. Obviously it depends on your destination object, but for me it was a List, and most likely it will implement ICollection.

    i.e.

    var destinationList = new List<someObject>();
    foreach (var item in itemList)
    {
      var stringArray = item.Split(new char[] { ';', ',' }, StringSplitOptions.RemoveEmptyEntries);
    
      if (stringArray.Length != 2)
      {
        //use the destinationList Count property to give us the index into the stringArray list
        throw new Exception("Item at row " + (destinationList.Count + 1) + " has a problem.");
      }
      else
      {
        destinationList.Add(new someObject() { Prop1 = stringArray[0], Prop2 = stringArray[1]});
      }
    }
    

    Not always applicable, but often enough to be worth mentioning, I think.

    Anyway, the point being that sometimes there is a non-obvious solution already in the logic you have...

    0 讨论(0)
提交回复
热议问题