tags:

views:

311

answers:

5

I'm working in C# and with a sorted List<T> of structs. I'm trying to iterate through the List and for each iteration I'd like to access the next member of the list. Is there a way to do this?

Pseudocode example:

foreach (Member member in List)
{
    Compare(member, member.next);
}
+25  A: 

You can't. Use a for instead

for(int i=0; i<list.Count-1; i++)
   Compare(list[i], list[i+1]);
munissor
This code is going to throw an index out of bounds exception for list[i + 1] on the last iteration of the loop...
froadie
@froadie that's what the -1 after Count is for
Bob
@Bob - thanks, you're right, didn't see that
froadie
@Bob and froadie: teh -1 after the Count won't prevent the exception on list[i+1]. The Count - 1 just adjusts for the zero-based index.
JMarsch
@Addie - @munissor makes a good point. While some of the syntax niceities are all well and good, it is something easier (and makes more sense) to use the good, old-fashioned syntax.
JasCav
+1 deleted my reply. This answer is more straightforward.
Ahmad Mageed
@JMarsch - the < instead of a <= adjusts for the zero-based index. The additional -1 takes care of exception on list[i + 1]
froadie
@Jason - thanks for the support ;) In those cases I also think that old-fashioned syntax is easier to use and read..
munissor
I approve of the elegance of this method. It's interesting to see how caught up people get in all the tools that exist and forget the simple things.
msarchet
This is fine, of course. As long as the collection in question implements IList<T>
Wayne
@Wayne you are right. I pointed this out on a comment on Mark Gravell answer
munissor
@froadie - gotcha -- I missed the < (vs <=)
JMarsch
+3  A: 

Use a regular for loop with an index, and compare list[i] and list[i+1]. (But make sure to only loop until the second-to-last index.)

Or, if you really want to use a foreach, you can keep a Member reference to the previous member and check the next time around. But I wouldn't recommend it.

froadie
+10  A: 

You could just keep the previous value instead:

T prev = default(T);
bool first = true;
foreach(T item in list) {
    if(first) {
        first = false;
    } else {
        Compare(prev, item);
    }
    prev = item;
}
Marc Gravell
This solution is better than mine if list is a ICollection or IEnumerable because you can't index the sigle elements of the list.
munissor
+1  A: 

LINQ might be your friend here. This approach will work with anything that's IEnumerable<T>, not just IList<T> collections, which is very useful if your collection never ends or is otherwise calculated on-the-fly:

class Program {
    static void Main(string[] args) {
        var list = new List<Int32> { 1, 2, 3, 4, 5 };
        foreach (var comparison in list.Zip(list.Skip(1), Compare)) {
            Console.WriteLine(comparison);
        }
        Console.ReadKey();
    }

    static Int32 Compare(Int32 first, Int32 second) {
        return first - second;
    }
}
Wayne
A: 

If one were so inclined, you could probably write an Extension method for this as well...

public static void ForEachNext<T>(this IList<T> collection, Action<T, T> func)
{
    for (int i = 0; i < collection.Count - 1; i++)
        func(collection[i], collection[i + 1]);
}

Usage:

List<int> numList = new List<int> { 1, 3, 5, 7, 9, 11, 13, 15 };

numList.ForEachNext((first, second) => 
{
    Console.WriteLine(string.Format("{0}, {1}", first, second));
});
Nick