开发者

Help to implement a ZipWithRatio extention method

I'm trying to find a elegant way to write a extention method that might be c开发者_StackOverflowalled MergeWithRatio or ZipWithRatio.

I expect it to have this signature..

public static IEnumerable<T> MergeWithRatio<T>(this IEnumerable<T> source, IEnumerable<T> mergeSequence, int ratio)
{
  ..
}

Example first.

var source   = new[]{1,2,3,4,5,6,7,8,9};
var mergeSeq = new[]{100,200};
var result = source.MergeWithRatio(mergeSeq, 3).ToArray();

result now contains [1, 2, 100, 3, 4, 200, 5, 6, 100, 7, 8, 200, 9]

Summing up: The mergeSeq is looped when/if finished and the yielding stops when 'source' is empty.

If possible I would prefere if the solution was lazy but it is not a requirement.

Any ideas or pointers?


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;
            }
        }
    }
}


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;
                }
            }
        }
    }
}


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜