Get Foreach index in C #

13

Normally I do iterations using the control statement for and so I get the index of the iteration easily, but the question I have is, is there any way to get the index of the iteration in a foreach c# ?

since I usually take it out in the following way:

int i=0;
foreach (var item in array)
{

   i++;
}

The other question would be, if there is a way to get the index in a different way from the one in the example, what is it?

    
asked by José Gregorio Calderón 09.05.2016 в 23:27
source

7 answers

5

I think the proper way to get the index in a foreach is the one you are using because it is a simple and optimal code and there are times when it can be interesting to use it.

An example of this is with the class ConcurrentBag

ConcurrentBag<int> cb = new ConcurrentBag<int>();
cb.Add(1);
cb.Add(2);
cb.Add(3);

int loop = 0;
foreach(int n in cb)
{
    loop++;
    Console.WriteLine("Loop: {0} | Number: {0}", loop, n);
}

In this case it does not make sense to use the for sequence because, among other things, you could add / remove items from another thread while the list is scrolled

Finally, what you should never do is use Array.IndexOf to get the index because you will force a search in the list for each iteration

string[] array = {"Item 1", "Item 2", "Item 3"};
foreach (var item in array)
{
    // Aquí se hará una búsqueda en la lista perdiendo rendimiento
    var index = Array.IndexOf(array, item);
    Console.WriteLine($"{index} - {item}");
}
    
answered by 11.05.2016 / 23:42
source
8
  

The other question would be, if there is a way to get the index in a different way than in the example

If you are browsing the elements to create a new list with these, you can use the extension method Select ( documentation ) which has an overload with the index.

var numeros = new [] { 1, 2, 3, 4, 5 };
var cuadrados = numeros.Select((n, i) => new { Valor = n * n, Indice = i + 1 });
    
answered by 10.05.2016 в 00:33
2

As an addition to what everyone else has written, I want to write a bit of theory.

for : It is a cycle that iterates within all a set of elements, either a list, or a Array (Generic example ) :

int[] Array = { 5, 4, 3, 2, 1 };
for (int i = 0; i < Array.Length; i++)
    Console.Write(Array[i] + ", ");

In each of your iterations you will find the value of the i element in Array , causing the following result:

5, 4, 3, 2, 1,

As you can see, yes, each element is actually accessed within Array .

With foreach this could be translated to:

foreach (int e in Array)
    Console.Write(e + ", ");

Which would produce the same output, now, we are talking about Array , an array is only a set of finite elements, if we are oriented to a List<T> , things change:

In a class whose main dependency is an iterator, why not use foreach to access each element of List<T> ? If we mention the performance, we are in nothing, the class List is ready for "fire" in the .NET Framework and the cycle foreach also, but, you can test the speed in each one . (Another generic example) :

public static void Main()
{
    List<int> Lista = new List<int>();
    Stopwatch S = new Stopwatch();

    Console.WriteLine("Iniciando cronometro para llenar la lista con 10,000 valores");
    S.Start();
    for (int i = 0; i < 10000; i++) Lista.Add(i);
    S.Stop();
    Console.WriteLine("Tiempo pasado llenar la lista: " + S.Elapsed.ToString());

    Console.WriteLine("\n\nIniciando cronometro para acceder a cada elemento usando el ciclo for:");
    S.Restart();
    for (int i = 0; i < Lista.Count; i++)
        Console.Write(Lista[i]);
    S.Stop();
    Console.WriteLine("\nTiempo transcurrido usando for: " + S.Elapsed.ToString());

    Console.WriteLine("\nIniciando cronometro para acceder a cada elemento usando foreach: ");
    S.Restart();
    foreach (int e in Lista)
        Console.Write(e);
    S.Stop();
    Console.WriteLine("\nTiempo transcurrido usando foreach: " + S.Elapsed.ToString());
}

(Run the previous example several times to check the results obtained)

Now, if what you want is to obtain the index of an element in a class that contains iterators or supports index , it is best to use your indexer or call its respective function IndexOf (As they mention Asier Villanueva and rsciriano )

IndexOf : It is a function that returns an integer with the current position of an element in your list, it is worth mentioning that this function is only available for the collections that are in the namespace System.Collections.Generic , its appearance is more or less like this:

int IndexOf<T>(this T[] item, T toSearch)
{
    for (int i = 0; i < item.Length; i++)
        if (item[i] == toSearch) return i;
    return -1; // No recuerdo si arroja al no encontrarlo, por lo que devolvemos null.
}

That is practically the same as iterating the list or collection to obtain the index of the current element, the practical uses of this function, come when you need to remove a specific element, example generic :

IList<string> Nombres = new List<string>() {
    "NaCl", "Miquel", "Asier", "Op", "Etc.."
};

And I need to specifically take my name, if it exists:

int IndexDeOp = Nombres.IndexOf("Op");

The value of IndexDeOp is 3 , so if you do not need to iterate within the list, this is your best option.

As a last mention, the cycle foreach can only be used is used in classes or "collections" that implement IEnumerable[<T>] , but this is not entirely necessary, it is enough that the following functions and properties are implemented: GetEnumerator , Current and MoveNext .

Here are some reference links:

for , foreach , a fiddle .

    
answered by 19.07.2016 в 16:25
1

You can get the index through the IndexOf method of the Array class:

        string[] array = {"Item 1", "Item 2", "Item 3"};
        foreach (var item in array)
        {
            var index = Array.IndexOf(array, item);
            Console.WriteLine($"{index} - {item}");
        }
        Console.ReadKey();

But the most logical thing is that if you need the index, use a for.

    
answered by 09.05.2016 в 23:36
0

I would use another type of loop, since with Foreach, you need to add a counter. You can still use Foreach and a separate counter.

I would use a while loop

int i=-1;

while(++i<array.Length)
  {
  // código del bucle..
  }
    
answered by 19.07.2016 в 11:47
-1

The correct thing would be using a for like:

for (int i = 0; i < array.Length; i++)
{
    //i te dará el indice automáticamente.
    Console.WriteLine(i); 
}
    
answered by 09.05.2016 в 23:53
-4

The Loop foreach is used in iterations in which it is not necessary to obtain or work with the index but with the objects, to work with the index it uses the loop for

    
answered by 09.05.2016 в 23:38