In a foreach loop I want to compare an element with the previous element that was read. How can I do that? What is the syntax for addressing a previous element in a foreach loop?
-
7Why not change it to a `for(int i =0; i < listSize; i++)` so you can access the element before? – Draken May 17 '16 at 15:24
-
4You could simply do it by using `temp variable`. – Pham X. Bach May 17 '16 at 15:24
-
1What is the "previous" element when you're at the start of the loop? (null, or perhaps you actually want to start looping from the second item) – Jamiec May 17 '16 at 15:26
-
`For loop` sometime has worse peformance than a `foreach loop` because you must go find the element `i` in a long `Collection` – Pham X. Bach May 17 '16 at 15:26
-
2@PhamX.Bach Who cares? Performance is not an argument. (In)ability to directly index items would be. – Ondrej Tucny May 17 '16 at 15:27
-
1Foreach is suppose to encapsulate the way you iterate over a collection, Therefore, if you want to compare elements in a specific order, you should iterate the collection differently and use indexes for doing that. – Amir Popovich May 17 '16 at 15:27
-
1[This answer has some nice information about how the `foreach` loop works](http://stackoverflow.com/a/43029/833070) – Draken May 17 '16 at 15:27
-
2@PhamX.Bach and somtimes `foreach loop` has worse performance than `for loop`, it depends on what is being done and the collection you are working with. – Scott Chamberlain May 17 '16 at 15:28
-
Setting a variable outside the loop that holds the previous item could be a solution. Also what @Draken suggests is good – Florian Schaal May 17 '16 at 15:29
6 Answers
You don't have that option built in with a foreach
loop.
You can either switch to a for
loop or use a variable.
Suppose you iterate through a list of objects, these are your options:
object prev = null;
foreach(var current in myListOfObjects)
{
if(current == prev)
{
// do stuff
}
// don't forget the next row!
prev = current;
}
or
for(var i = 1; i < myListOfObjects.count, i++) // Note: starting from 1 to avoid another condition inside the loop.
{
if(myListOfObjects[i] == myListOfObjects[i-1])
{
// do stuff
}
}

- 79,642
- 10
- 69
- 121
Everything is better with Bluetooth extension methods:
public static class EnumerableExtensions
{
public struct CurrentAndPrevious<T>
{
public T Current { get; private set; }
public T Previous { get; private set; }
public CurrentAndPrevious(T current, T previous) : this()
{
Previous = previous;
Current = current;
}
}
public static IEnumerable<CurrentAndPrevious<T>> WithPrevious<T>(this IEnumerable<T> enumerable)
{
var previous = default(T);
using(var enumerator = enumerable.GetEnumerator())
{
while(enumerator.MoveNext())
{
yield return new CurrentAndPrevious<T>(enumerator.Current, previous);
previous = enumerator.Current;
}
}
}
}
var items = new[] { 1, 2, 3, 4, 5 };
foreach(var item in items.WithPrevious())
{
Console.WriteLine(item.Previous + " " + item.Current);
}
You might need to tweak this depending on how you want first and last elements handled.

- 113,561
- 39
- 200
- 288
-
Your foreach example might be a little confusing for someone new to C#, it might be better to split array initization and the use of .WithPrevious(). – Scott Chamberlain May 17 '16 at 15:31
-
3While I love this solution, I hate the use of `Tuple` here. Its so unintuative what `Item1` and `Item2` are. For the sake of declaring a struct with properties `Current` and `Previous` ... I'd personally do that. – Jamiec May 17 '16 at 15:33
-
@Jamiec My thoughts exactly, but I could not come up with a good name for this "value with previous value" type thing. – Anton Gogolev May 17 '16 at 15:36
-
`EnumerableElementWithPrevious
` - although thats quite verbose. And now im wondering if a struct can be generic... might need to be a class. – Jamiec May 17 '16 at 15:42 -
1
You can loop over a bit modified source
instead of initial, say ListOfMyObjects
:
MyObject prior = default(MyObject);
var source = ListOfMyObjects
.Select(item => {
var result = new {
Current = item,
Prior = prior,
};
prior = item; // side effect, not a good practice
return result;
});
So you can loop
foreach(var item in source) {
if (item.Prior == item.Current) {
...
}
}

- 180,369
- 20
- 160
- 215
A foreach
itself has no syntax 'for addressing a previous element'. There are two options, depending on the characteristics of the collection and also the notion of a 'previous' element in respect of the first one. The following the examples are a little bit simplistic, but you should be able to choose the right path and fine-tune the details.
Option 1: Use a temporary variable
Works well if there's no cheap (performance-wise) way to index elements in the sequence, and you are OK with 'pretending' there's an empty (null
, or default(T)
) item before the very first item.
T previous = default(T); // corresponds to null for reference types
foreach (T item in sequence)
{
… work with previous and item here…
// the current 'item' is the new 'previous' for the next iteration
previous = item;
}
Note that if T is a value type, your would be actually copying the values themselves.
Option 2: Use a for
loop and indexing
Works well if there is a cheap (performance-wise) way to index individual elements directly. List<T>
and arrays are good examples here.
// indexing from 1, i.e. from the second item in the sequence
for (int i = 1; i < sequence.Count; i++)
{
var previous = sequence[i-1]; // this is obviously the previous item
var current = sequence[i]; // this is obviously the current item
}

- 133,658
- 13
- 134
- 193

- 27,626
- 6
- 70
- 90
Similar to using a temp variable, however this solution moves the scope of the temp variable inside the loop
var collection = new List<int>() { 1, 2, 3, 4, 5 };
foreach (var item in collection)
{
var currentIndex = collection.IndexOf(item);
if (currentIndex > 0 && currentIndex < collection.Count)
{
var previousItem = collection[currentIndex - 1];
}
}

- 2,338
- 1
- 20
- 25
As mentioned by Pham X, one easy way to do this would be a temp variable.
ObjectType temp_object = null;
foreach(var entry in ListOfObjects)
{
if(temp_object==null)
{
//this is the first time through...
temp_object=entry;
}
else
{
//it's anything after the first loop
if(entry==temp_object) Console.WriteLine("There is a match between two entries.");
else temp_object=entry;
}
}

- 33
- 5