Enumerable.Zip is a fascinating LINQ operator. It threads or merges two collections of any type or length. It is not a very well known operator and I myself only come across it a little while ago.
Let’s say we have 2 collections. The first is an integer collection and the second is a string collection as below.
var numbers = new[] { 1, 2, 3 };
var romanNumerals = new[] { "I", "II", "III" };
Let’s say we want to merge the two collections to produce a third collection like below
var result = new[]
{
"1 in Roman Numerals is I",
"2 in Roman Numerals is II",
"3 in Roman Numerals is III",
}
In the past, in order to achieve this, I would need to use a for loop through the numbers collection, use the index to get the item at the same index in the Roman Numerals collection and then use string interpolation to produce the final result. I would also need to check if the index is within range of the second collection in case it is of a smaller size than the first collection.
The Zip LINQ operator can achieve this with a single line of code. We call Zip on the first collection. Zip requires 2 parameters:
- A collection of any type to be zipped with the first.
- A func or delegate for how to combine the 2 collections.
var result = numbers.Zip(romanNumerals,
(number, roman) => $"{number} in Roman Numerals is {roman}");
As mentioned early, the two collections don’t have to be same length. The result will have the length of the smaller collection. The following 2 examples both return the same result as the code above.
var numbers = Enumerable.Range(1, 100).ToArray();
var romanNumerals = new[] { "I", "II", "III" };
var result = numbers.Zip(romanNumerals,
(number, roman) => $"{number} in Roman Numerals is {roman}");
var numbers = new[] { 1, 2, 3 };
var romanNumerals = new[] { "I", "II", "III", "IV", "V" };
var result = numbers.Zip(romanNumerals,
(number, roman) => $"{number} in Roman Numerals is {roman}");