帮助实现 ZipWithRatio 扩展方法

发布于 2024-10-24 00:42:19 字数 599 浏览 1 评论 0原文

我正在尝试找到一种优雅的方式来编写可能称为 MergeWithRatio 或 ZipWithRatio 的扩展方法。

我希望它有这个签名..

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

首先是示例。

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 在完成时循环,并且当“source”为空时停止生成。

如果可能的话,我希望解决方案是惰性的,但这不是必需的。

有什么想法或指示吗?

I'm trying to find a elegant way to write a extention method that might be called 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

情话墙 2024-10-31 00:42:19

这将起作用并返回预期的输出:

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

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;
            }
        }
    }
}
烟沫凡尘 2024-10-31 00:42:19

这是我的实现:

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

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;
                }
            }
        }
    }
}
追星践月 2024-10-31 00:42:19
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 输入值`等的一些检查。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文