Помогите реализовать метод расширения ZipWithRatio - PullRequest
2 голосов
/ 21 марта 2011

Я пытаюсь найти элегантный способ написать метод расширения, который может называться MergeWithRatio или ZipWithRatio.

Я ожидаю, что у него будет эта подпись ..

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

Пример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();

Результат теперь содержит [1, 2, 100, 3, 4, 200, 5, 6, 100, 7, 8, 200, 9]

Суммирование:MergeSeq зацикливается, когда / если закончено, и сдача прекращается, когда «источник» пуст.

Если возможно, я бы предпочел, если бы решение было ленивым, но это не требование.

Любые идеиили указатели?

Ответы [ 3 ]

2 голосов
/ 21 марта 2011

Это будет работать и возвращает ожидаемый результат:

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;
            }
        }
    }
}
1 голос
/ 21 марта 2011

Вот моя реализация:

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;
                }
            }
        }
    }
}
0 голосов
/ 21 марта 2011
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;
            }
        }
    }
}

Плюс некоторые проверки mergeSequenceEnumerator.MoveNext(), ratio входное значение` и т. Д.

...