Archive for category LINQ

Zip multiple sequences together

The new Zip extension method in .NET 4.0 is very useful, but what if you want to zip more than two sequences together?

Luckily the implementation of Zip is very straightforward. You can easily implement it yourself if you don’t target .NET 4.0 yet. Likewise it is easy to implement zipping multiple sequences yourself. This allows you to do the following:

byte[] reds = new { 0, 1, 2 };
byte[] greens = new { 3, 4, 5 };
byte[] blues = new { 6, 7, 8 };
var mergedColors = reds.Zip( greens, blues, Color.FromRgb );

mergedColors will contain (0, 3, 6), (1, 4, 7) and (2, 5, 8). With the regular zip operator you would have to write the following:

var mergedColors = reds
                .Zip( greens, ( r, g ) => Color.FromRgb( r, g, 0 ) )
                .Zip( blues, ( c, b ) => Color.FromRgb( c.R, c.G, b ) );

Besides being more complex, it most likely is also less efficient due to the need for the temporary intermediate objects.

The implementation of the Zip for three sequences is as simple as:

public static IEnumerable Zip(
    this IEnumerable first,
    IEnumerable second,
    IEnumerable third,
    Func resultSelector )
{
    Contract.Requires(
        first != null && second != null && third != null && resultSelector != null );

    using ( IEnumerator iterator1 = first.GetEnumerator() )
    using ( IEnumerator iterator2 = second.GetEnumerator() )
    using ( IEnumerator iterator3 = third.GetEnumerator() )
    {
        while ( iterator1.MoveNext() && iterator2.MoveNext() && iterator3.MoveNext() )
        {
            yield return resultSelector(
                iterator1.Current,
                iterator2.Current,
                iterator3.Current );
        }
    }
}
Advertisements

Leave a comment