非常简单的情况:我有一个项目列表(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
在我看来这可行:
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));
我得到: