是否可以在带有“yield”的方法内对同一个 Ienumerable 使用“foreach”两次或更多次?

问题描述 投票:0回答:1

非常简单的情况:我有一个项目列表(1,2,3,4,5,6,7,8,9,10)。我需要过滤它并删除一些第一个元素和一些最后一个元素,并从中间获取一些项目(例如我需要获取(5,6,7,8))。

我写了这个方法:

IEnumerable<int> GetCapturedTimeLapsesWithRatios(IEnumerable<int> allTimeLapsesProfitabilitiesResult, int from, int to)
{
    foreach (var item in allTimeLapsesProfitabilitiesResult)
    {
        if (item <= from)
        {
            Console.WriteLine(item);
            continue;
        }
        else
        {
            if (item >= to)
            {
                Console.WriteLine("if (item >= to) " + item);
                yield return item;
                yield break;
            }
            else
            {
                Console.WriteLine("else " + item);
                yield return item;
                break;
            }
        }
    }

    foreach (var item in allTimeLapsesProfitabilitiesResult)
    {
        if (item < to)
        {
            Console.WriteLine("if (item < to) " + item);
            yield return item;
        }
        else
        {
            Console.WriteLine("else " + item);
            yield return item;
            yield break;
        }
    }
}
GetCapturedTimeLapsesWithRatios(new List<int>() {0,1,2,3,4,5,6,7,8,9,10 }, 4, 8);

我得到了完全错误的结果:

{ 5, 0, 1, 2, 3, 4, 5, 6, 7, 8 }

控制台显示的行数比我预期的多

0
1
2
3
4
else 5
if (item < to) 0    // wrong line
if (item < to) 1    // wrong line
if (item < to) 2    // wrong line
if (item < to) 3    // wrong line
if (item < to) 4    // wrong line
if (item < to) 5    // wrong line
if (item < to) 6
if (item < to) 7
else 8

我看到第二个“foreach”从“0”元素开始迭代,但我预计它从“6”元素开始迭代,因为第一个“foreach”处理了前 5 个元素。

那么有没有一种方法可以在具有“yield”的方法内的同一个 Ienumerable 上多次使用“foreach”(每个“foreach”具有不同的过滤)?或者也许我做错了?

PS:上面的代码是一个虚拟代码,因为我的实际代码更复杂,所以我不能仅使用标准 LINQ 方法,例如

new List<int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }.SkipWhile(i => i <= 4).TakeWhile(i => i <= 8)

更新:我使用“GetEnumerator()”重写了我的代码,现在它可以按我的预期工作,但是现在的可读性要差得多,所以我想知道有没有办法让它更具可读性?

IEnumerable<int> GetCapturedTimeLapsesWithRatios(IEnumerable<int> allTimeLapsesProfitabilitiesResult, int from, int to)
{
    using (var enumerator = allTimeLapsesProfitabilitiesResult.GetEnumerator())
    {
        do
        {
            if (!enumerator.MoveNext())
                yield break;

            var item = enumerator.Current;
            if (item <= from)
            {
                Console.WriteLine(item);
                continue;
            }
            else
            {
                if (item >= to)
                {
                    Console.WriteLine("if (item >= to) " + item);
                    yield return item;
                    yield break;
                }
                else
                {
                    Console.WriteLine("else " + item);
                    yield return item;
                    break;
                }
            }
        } while (true);

        do
        {
            if (!enumerator.MoveNext())
                yield break;
            var item = enumerator.Current;
            if (item < to)
            {
                Console.WriteLine("if (item < to) " + item);
                yield return item;
            }
            else
            {
                Console.WriteLine("else " + item);
                yield return item;
                yield break;
            }
        } while (true);
    }
}
GetCapturedTimeLapsesWithRatios(new List<int>() {0,1,2,3,4,5,6,7,8,9,10 }, 4, 8);

更新:mjwills 询问:

那么这是一个 XY 问题,而您向我们隐瞒了信息 需要全力帮助您。告诉我们更多有关其本质的信息 复杂的代码。

好的。我有

DateOnly
(间隔的最终点)的升序排序列表,之前的
DateOnly
是当前
DateOnly
的起点,所以我有一个升序的间隔序列。我有输入间隔(
from
to
),并且我需要返回仅包含“包装”输入间隔的间隔的列表。

例如,给出以下列表:

2024-10-01
2024-10-10
2024-10-15
2024-10-25
2024-10-28
2024-10-30

所以我有间隔列表:

1970-01-01 to 2024-10-01
2024-10-01 to 2024-10-10
2024-10-10 to 2024-10-15
2024-10-15 to 2024-10-25
2024-10-25 to 2024-10-28
2024-10-28 to 2024-10-30

输入间隔:

2024-10-12 to 2024-10-27

我需要在升序列表中找到“包裹”输入间隔的间隔,并且我需要返回

DateOnly
-s。

所以,对于这个例子,我需要返回:

2024-10-15
2024-10-25
2024-10-28
c# ienumerable yield
1个回答
0
投票

在我看来这可行:

IEnumerable<DateOnly> GetCapturedTimeLapsesWithRatios(IEnumerable<DateOnly> input, DateOnly @from, DateOnly @to) =>
    input
        .StartWith(new DateOnly(1970, 1, 1))
        .Zip(input)
        .Where(x => x.Second >= @from && x.First <= @to)
        .Select(x => x.Second);

当我使用这些数据运行时:

var list = new List<DateOnly>()
{
    new DateOnly(2024, 10, 1),
    new DateOnly(2024, 10, 10),
    new DateOnly(2024, 10, 15),
    new DateOnly(2024, 10, 25),
    new DateOnly(2024, 10, 28),
    new DateOnly(2024, 10, 30),
};

var results = GetCapturedTimeLapsesWithRatios(list, new DateOnly(2024, 10, 12), new DateOnly(2024, 10, 27));

我得到:

results

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.