Iterate two Lists or Arrays with one ForEach statement in C#

This is known as a Zip operation and will be supported in .NET 4.

With that, you would be able to write something like:

var numbers = new [] { 1, 2, 3, 4 };
var words = new [] { "one", "two", "three", "four" };

var numbersAndWords = numbers.Zip(words, (n, w) => new { Number = n, Word = w });
foreach(var nw in numbersAndWords)
{
    Console.WriteLine(nw.Number + nw.Word);
}

As an alternative to the anonymous type with the named fields, you can also save on braces by using a Tuple and its static Tuple.Create helper:

foreach (var nw in numbers.Zip(words, Tuple.Create)) 
{
    Console.WriteLine(nw.Item1 + nw.Item2);
}

If you don't want to wait for .NET 4.0, you could implement your own Zip method. The following works with .NET 2.0. You can adjust the implementation depending on how you want to handle the case where the two enumerations (or lists) have different lengths; this one continues to the end of the longer enumeration, returning the default values for missing items from the shorter enumeration.

static IEnumerable<KeyValuePair<T, U>> Zip<T, U>(IEnumerable<T> first, IEnumerable<U> second)
{
    IEnumerator<T> firstEnumerator = first.GetEnumerator();
    IEnumerator<U> secondEnumerator = second.GetEnumerator();

    while (firstEnumerator.MoveNext())
    {
        if (secondEnumerator.MoveNext())
        {
            yield return new KeyValuePair<T, U>(firstEnumerator.Current, secondEnumerator.Current);
        }
        else
        {
            yield return new KeyValuePair<T, U>(firstEnumerator.Current, default(U));
        }
    }
    while (secondEnumerator.MoveNext())
    {
        yield return new KeyValuePair<T, U>(default(T), secondEnumerator.Current);
    }
}

static void Test()
{
    IList<string> names = new string[] { "one", "two", "three" };
    IList<int> ids = new int[] { 1, 2, 3, 4 };

    foreach (KeyValuePair<string, int> keyValuePair in ParallelEnumerate(names, ids))
    {
        Console.WriteLine(keyValuePair.Key ?? "<null>" + " - " + keyValuePair.Value.ToString());
    }
}

You can use Union or Concat, the former removes duplicates, the later doesn't

foreach (var item in List1.Union(List1))
{
   //TODO: Real code goes here
}

foreach (var item in List1.Concat(List1))
{
   //TODO: Real code goes here
}

Tags:

C#