score:2

Accepted answer

This would work and returns the expected output:

public static IEnumerable<T> MergeWithRatio<T>(this IEnumerable<T> source, IEnumerable<T> mergeSequence, int ratio)
{
    int currentRatio  = 1;
    bool mergeSequenceIsEmpty = !mergeSequence.Any();

    using (var mergeEnumerator = mergeSequence.GetEnumerator())
    {
        foreach (var item in source)
        {
            yield return item;
            currentRatio++;
            if (currentRatio == ratio &&  !mergeSequenceIsEmpty)
            {
                if (!mergeEnumerator.MoveNext())
                {
                    mergeEnumerator.Reset();
                    mergeEnumerator.MoveNext();
                }
                yield return mergeEnumerator.Current;
                currentRatio = 1;
            }
        }
    }
}

score:0

public static IEnumerable<T> MergeWithRatio<T>(this IEnumerable<T> source, IEnumerable<T> mergeSequence, int ratio)
{
    using (IEnumerator<T> sourceEnumerator = source.GetEnumerator(), 
                          mergeSequenceEnumerator = mergeSequence.GetEnumerator())
    {
        int i = 1;
        while (sourceEnumerator.MoveNext())
        {
            yield return sourceEnumerator.Current;
            i++;
            if (i == ratio)
            {
                if (!mergeSequenceEnumerator.MoveNext())
                {
                    mergeSequenceEnumerator.Reset();
                    mergeSequenceEnumerator.MoveNext();
                }
                yield return mergeSequenceEnumerator.Current;
                i = 1;
            }
        }
    }
}

Plus some checks on mergeSequenceEnumerator.MoveNext(), ratio input value`, etc.

score:1

Here is my implementation:

public static IEnumerable<T> MergeWithRatio<T>(this IEnumerable<T> source, IEnumerable<T> mergeSequence, int ratio)
{
    if (source == null)
    {
        throw new ArgumentNullException("source");
    }

    if (mergeSequence == null)
    {
        throw new ArgumentNullException("mergeSequence");
    }

    if (ratio <= 1)
    {
        throw new ArgumentOutOfRangeException("ratio must be greater one.");
    }

    return MergeWithRatioImpl(source, mergeSequence, ratio);
}

private static IEnumerable<T> MergeWithRatioImpl<T>(this IEnumerable<T> source, IEnumerable<T> mergeSequence, int ratio)
{
    bool mergeSequenceContainsElements = true;
    int i = 1;
    ratio--;

    using (var sourceEnumerator = source.GetEnumerator())
    using (var mergeSequenceEnumerator = mergeSequence.GetEnumerator())
    {
        while (sourceEnumerator.MoveNext())
        {
            yield return sourceEnumerator.Current;

            if (i++ % ratio == 0)
            {
                if (!mergeSequenceEnumerator.MoveNext())
                {
                    // ToDo: Should we cache the current values for the case the
                    //       enumerator can't be reset?
                    mergeSequenceEnumerator.Reset();
                    mergeSequenceContainsElements = mergeSequenceEnumerator.MoveNext();
                }

                if (mergeSequenceContainsElements)
                {
                    yield return mergeSequenceEnumerator.Current;
                }
            }
        }
    }
}

Related Articles