.net-core - 如何防止枚举器聚合所有项目?
问题描述
我有一个简单的函数,我只是在这里用作示例。这是一个无限的枚举!
public static IEnumerable<int> Roll()
{
while (true)
{
yield return new Random().Next(1, 6);
}
}
我希望这个函数在特定数量的时钟滴答声中保持滚动,所以我有这个方法:
public static List<T> Ticks<T>(this IEnumerable<T> data, int time)
{
var list = new List<T>();
Stopwatch timer = null;
foreach (var item in data)
{
if (timer == null)
{
timer = Stopwatch.StartNew();
}
if (timer.ElapsedTicks < time)
{
list.Add(item);
}
else
{
break;
}
}
timer?.Stop();
return list;
}
但我真的不喜欢我必须如何写,因为我宁愿有更多这样的东西:
public static List<T> Ticks2<T>(this IEnumerable<T> data, int time)
{
var list = new List<T>();
Stopwatch timer = Stopwatch.StartNew();
using (var en = data.GetEnumerator())
{
while (timer.ElapsedTicks < time && en.MoveNext())
{
list.Add(en.Current);
}
}
timer.Stop();
return list;
}
但是后一个函数将失败,因为 GetEnumerator() 方法将聚合所有数据并以不定式枚举的形式进行,这需要永远......
等等......我错了......结果太快了,我的列表跑了内存不足...幸运的是,它没有聚合...
Ticks() 方法工作正常,顺便说一句!我可以使用这个:
Console.WriteLine( Watch.Roll().Ticks(10000).AllToString().AllJoin(", ") );
它会一直滚动到 10,000 个滴答声过去,将所有内容转换为字符串并加入所有内容,同时保留方法链。这很重要,顺便说一句。我不能接受任何会破坏方法链的答案。请记住,这只是一个示例。
不,我不能对 Roll() 方法进行任何更改。该方法是只读的...
那么,如何在不聚合所有数据的情况下重写这个 Ticks() 方法,使其更类似于 Ticks2() 方法?
对于那些对 AllToString() 和 AllJoin 方法感到好奇的人:
public static IEnumerable<string> AllToString<T>(this IEnumerable<T> data) => data.Select(item => item.ToString());
public static string AllJoin<T>(this IEnumerable<T> data, string separator) => string.Join(separator, data.AllToString());
这两种方法对于您将使用枚举并需要字符串输出的其他解决方案非常实用。
解决方案
public static IEnumerable<T> Ticks<T>( this IEnumerable<T> source, Int64 totalTicks )
{
Stopwatch sw = Stopwatch.StartNew();
foreach( T item in source )
{
if( sw.ElapsedTicks < totalTicks )
{
yield return item;
}
else
{
yield break;
}
}
}
您实际上根本不需要任何自定义扩展方法:您也可以只使用TakeWhile
instead of Ticks
、Select
instad ofAllToString()
和Aggregate
instead of AllJoin
:
Stopwatch sw = Stopwatch.StartNew();
String all = Watch.Roll()
.TakeWhile( _ => sw.ElapsedTicks < 10000 )
.Select( i => i.ToString() )
.Aggregate(
new StringBuilder(),
( s, sb ) => sb.Append( s ).Append(", "),
sb => sb.ToString()
);
Console.WriteLine( all ):
推荐阅读
- php - 如何从 PHP 中的字符串中获取特定的字符串值?
- wpf - DataTable 到 Combobox - 未在 UI 中设置 SelectedValue,返回两个值
- java - maven-bundle-plugin 不包括 Import-Package
- salesforce - 视觉力量页面未能在 Lightning 的 EU6 组织中显示
- javascript - 如何使用 Javascript 或 Java 获取 CSV 动态更改的实际数字
- r - 将一行数值变量除以一个常数
- swift - 如何从 Firebase 中仅检索 UID 并在 TableView 中显示
- angular6 - “在‘@angular/core’中找不到导出‘Δinject’
- android-studio - 颤振附加 - 哎呀;Flutter 意外退出
- php - 将表迁移到 db 时出错...表已存在