I want to concatenate the elements of two sequences, producing a single sequence containing all the elements of the original two, but with their elements interleaved.
The Concat
LINQ method can do the concatenation but without the interleaving, so I need something special.
The rules for interleaving are these:
- For each pair of elements a
selector
function should be called, and the element selected should be either the first or the second, depending on theboolean
result of the function (true
: first,false
: second)
Here is a practical example of what I want to achieve:
var sequence1 = new int[] { 1, 2, 3 };
var sequence2 = new int[] { 11, 12, 13 };
var result = sequence1.ConcatInterleaved(sequence2, (a, b) => (a + b) % 3 == 0);
Console.WriteLine(String.Join("\r\n", result));
Expected output:
1 // Because (1 + 11) % 3 == 0, the first is selected
11 // Because (2 + 11) % 3 != 0, the second is selected
12 // Because (2 + 12) % 3 != 0, the second is selected
2 // Because (2 + 13) % 3 == 0, the first is selected
13 // Because (3 + 13) % 3 != 0, the second is selected
3 // Because sequence2 has no more elements, the next element of sequence1 is selected
I want a LINQ solution so that the actual concatenation can be deferred, in the spirit of the build-in LINQ methods. This is my current attempt:
public static IEnumerable<TSource> ConcatInterleaved<TSource>(
this IEnumerable<TSource> source,
IEnumerable<TSource> other,
Func<TSource, TSource, bool> selector)
{
// What to do?
}
Update: I changed the example so it doesn't look like a simple alternating interleaving.
A clarification about the selector
function: This function is not applied to preselected pairs of the two sequences, like it happens in the Zip
method. The pairs are not predefined. After each selection a new pair is formed, containing the rejected element of the previous selection, and a new element from the previously selected sequence.
For example with the selector (a, b) => true
the ConcatInterleaved
becomes equivalent to Concat
: All elements of sequence1 are returned, followed by all elements of sequence2. Another example: with the selector (a, b) => false
all elements of sequence2 are returned, followed by all elements of sequence1.