Get previous element in foreach

Asked

Viewed 812 times

5

It is possible to take an element from the previous to current position using the repeat loop foreach?

For example, whenever I need to take an element previous to the current position of the loop, I use the loop for, as follows:

List<int> ListaDados = new List<int>();

ListaDados.Add(1); ListaDados.Add(2); ListaDados.Add(3); ListaDados.Add(5);

for(int i=1; i < ListaDados.Count; i++) {      
    var elementoAtual = ListaDados[i];
    var elementoAnterior = ListaDados[i-1];
}
  • 2

    No, by definition the foreach will invoke Ienumerable.Getenumerator to perform its increment, it does not use index as FOR.

  • 2

    Just as a detail, this code would give execution error in the first iteration of for, since there is no element in the position -1 of ListaDados

  • 2

    Use a for common is by far the best solution.

2 answers

5


Yes, it is possible:

using static System.Console;
using System.Collections.Generic;

public class Program {
    public static void Main() {
        var lista = new List<int>() { 1, 2, 3, 4 };
        var anterior = 0;
        foreach (var item in lista) {
            WriteLine($"Soma o atual e anterior { anterior + item }");
            anterior = item;
        }
    }
}

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

The exact way to implement this depends on your need. In some cases it may be interesting to put a comparison to avoid the first execution, since C# does not treat this execution differently and does not intend to have this in the language.

In structures you create or can extend it is possible to create a specific enumerator that gives you access to the previous element, but that is another matter.

I don’t like the other answer, it is absurdly slower, with possibly quadratic complexity (in List certainly, and it’s double). And I think it’s even wrong because if you have duplicate items will give error.

0

As Gabriel commented on, "by definition the foreach will invoke the Ienumerable.Getenumerator to make its increment, it does not use the index as the for".

But there is an alternative (which I believe is not very viable) if you really want to use the foreach:

List<int> ListaDados = new List<int>();

ListaDados.Add(1); ListaDados.Add(2); ListaDados.Add(3); ListaDados.Add(5);

freach (int elementoAtual in ListaDados){

    if (ListaDados.IndexOf(elementoAtual) == 0)
        // não existe elemento anterior
    else
    {
        var elementoAnterior = ListaDados.ElementAt(ListaDados.IndexOf(elementoAtual));

        //todo: seu código
    }
}
  • Read my edition, I haven’t analyzed it deeply, if you want to dispute it. I did not mention the possibility of having a current element that is 0, and will execute the first one as if it had a previous one. This is actually the same problem of having duplicates and it may be that in some use it is not a problem, as I say in the answer. In mine would have if it’s a sum maybe I need to use a flag or another mechanism to treat the former, so at that point it is not enough to be a mistake in your reply.

Browser other questions tagged

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