How to get the current iteration index of a foreach?

Asked

Viewed 5,699 times

5

Usually in order to get the current iteration index within a foreach, I do it this way:

int i=0;
foreach (var elemento in list)
{    
   // Qualquer coisa
   i++;
}

I believe there are other methods to get the iteration index (see you around "beautiful" that the presented), what are?

5 answers

8


Actually if you really need the index, the right thing is to use the for.

If you don’t want to use the right tool for the problem, the most obvious solution is the one presented in the question.

Otherwise the solution that people usually make is to use LINQ, what I find an exaggeration for the problem and very rarely is a better solution than the previous ones in any analysis that is made - if you do a general analysis, I doubt that it is good in any situation. It would be something like that:

foreach (var pair in list.Select((x, i) => new {Index = i, Value = x})) {
    WriteLine($"{pair.Index}: {pair.Value}");
}

Behold working in the ideone. And in the .NET Fiddle. Also put on the Github for future reference.

I find it less readable, less performative and I can’t see any gain.

Some prefer to create some abstraction on top of that, such as an extension method that hides a little the implementation details, or a class that handles it. In rare cases I find it appropriate. Depending on the case (where a method replaces the loop) it changes the semantics and few programmers know how to handle it right. Ends up being an exaggeration to avoid the obvious and simple use.

What could make it a little better, something like that:

foreach (var pair in list.IndexPair()) {
    WriteLine($"{pair.Index}: {pair.Value}");
}

public static class IEnumerableExt {
    public static IEnumerable<T> IndexPair(this IEnumerable<T> enumerable) {
        return enumerable.Select((x, i) => new {Index = i, Value = x});
    }
}

I’ve seen some solutions so bizarre that I refuse to post here.

  • 2

    @ramaral I hope not :) I saw some people posting something like this, but I think just out of curiosity. It has language that no longer has the for, and worse doesn’t have a foreachindexable that would make sense for some cases, but not for all, I think a mistake. I think it is good to avoid the for when it gives, but not at any cost.

  • 1

    When I learned Lilli, I was excited to use it in everything. Nowadays, knowing the possible losses in a failed implementation (let’s be honest and agree that 90% of those who use Linq do not know what it actually does), I prefer to use in cases where the foreach can not do right ( joins / predicated wheres, etc). Good to know, ... not very good to implement in production. My opinion.

  • @Ericwu became your fan :D

5

The foreach is a more elegant loop form, to iterate over elements of a Collection in various languages. In the C# language it is used to iterate over collections that implement the IEnumerable. So he goes calling the method GetEnumerator what returns a Enumerator. In that Enumerator we have the properties:

MoveNext() atualiza o Current com o próximo objeto

and

Current retorna o Enumerator atual

So the concept of index in foreach is not found. Rather than using a variable outside of the foreach for index control, it is more reasonable in my opinion to use the normal:

for (int i = 1; i <= 5; i++)
{
   list[i];
   Console.WriteLine(i);
}

4

The foreach does not possess knowledge of the current index to expose it in an elegant way, you have to control a variable manually even. This happens because the foreach is an independent structure of a data type that needs to work with number indexing. It works only on the interface IEnumerable and IEnumerator.

The fact that it does not have an index in the foreach makes perfect sense, since you can implement using the foreach in structures that do not have indexing, such as a LinkedList

1

I do not know is the most effective and performative way, but following the analogy to perform the interaction on top of a list in python, we can get the index in a foreach in c# and interact using this index on top of the list as follows.

Example:

 var lista = new List<int>(){ {100}, {200}, {300}, {400}, {500}, {600}, {700},  
                              {800}, {900}, {1000} 
 };     
foreach(var index in Enumerable.Range(0, lista.Count()).ToList())
    Console.WriteLine("Index item: "+ index + " valor item na lista: " + 
                       lista[index]);       
}

This way instead of performing the interaction through the foreach on top of the list directly, a new list of indices is created through the (Enumerable.Range) from 0 to the total size of the list, thus creating a list of indices from 0 to the size of the list in a range of 1 in 1.

So instead of interacting directly on top of the desired list, the interaction is made on top of the index list where each index will match the position of the desired element in the list, so it is possible to access and obtain the index of the list element in a similar way to a traditional one.

Following example in . NET Fiddle: https://dotnetfiddle.net/cDyfdg

0

You use for to have control of the iteration, and use Elementat to get the value

static void Main(string[] args)
        {
                var lista = new List<teste>() {
                    new teste("João", 12),
                    new teste("Maria", 12),
                    new teste("José", 12),
                    new teste("Carlos", 12),
                    new teste("Juliana", 12),
                };


                for (int i = 0; i < lista.Count(); i++)
                {
                    Console.WriteLine(lista.ElementAt(i).nome);
                }


                Console.ReadKey();
            }

            public class teste
            {
                public teste()
                { }
                public teste(string _nome, int _idade)
                {
                    this.nome = _nome;
                    this.idade = _idade;
                }
                public string nome;
                public int idade;
            }

Browser other questions tagged

You are not signed in. Login or sign up in order to post.