c# - "Unzip"IEnumerable 在 C# 或最佳替代方案中动态

标签 c# algorithm linq ienumerable enumerator

假设您有一个返回惰性枚举对象的函数:

struct AnimalCount
{
    int Chickens;
    int Goats;
}

IEnumerable<AnimalCount> FarmsInEachPen()
{
    ....
    yield new AnimalCount(x, y);
    ....
}

您还有两个函数使用两个单独的 IEnumerable,例如:

ConsumeChicken(IEnumerable<int>);
ConsumeGoat(IEnumerable<int>);

你怎么能调用 ConsumeChickenConsumeGoat 而不 a) 预先转换 FarmsInEachPen() ToList() 因为它可能有两个无数的记录, b) 没有多线程。

基本上:

ConsumeChicken(FarmsInEachPen().Select(x => x.Chickens));
ConsumeGoats(FarmsInEachPen().Select(x => x.Goats));

但不强制双重枚举。

我可以用多线程来解决它,但是每个列表都有一个缓冲队列会变得不必要地复杂。

因此,我正在寻找一种方法,将 AnimalCount 枚举器拆分为两个 int 枚举器,而无需完全评估 AnimalCount。同步运行 ConsumeGoatConsumeChicken 没有问题。

我能感觉到解决方案就在我的掌握之外,但我还没有完全解决。我正在考虑返回 IEnumerable 的辅助函数的思路,该函数返回 ConsumeChicken 并且每次使用迭代器时,它都会在内部调用 ConsumeGoat,从而锁步执行这两个函数。除了,当然,我不想多次调用 ConsumeGoat..

最佳答案

我不认为有办法做你想做的事,因为ConsumeChickens(IEnumerable<int>)ConsumeGoats(IEnumerable<int>)正在按顺序调用,它们中的每一个都分别枚举一个列表 - 如果没有两个单独的列表枚举,您如何期望它工作?

根据情况,更好的解决方案是ConsumeChicken(int)ConsumeGoat(int)方法(每个消耗一个单个项目),并交替调用它们。像这样:

foreach(var animal in animals)
{
    ConsomeChicken(animal.Chickens);
    ConsomeGoat(animal.Goats);
}

这将枚举 animals仅收集一次。


另外,请注意:根据您的 LINQ 提供程序以及您尝试执行的具体操作,可能会有更好的选择。例如,如果您尝试使用 linq-to-sql 或 linq-to-entities 从数据库中获取鸡和山羊的总和,则以下查询..

from a in animals
group a by 0 into g
select new 
{
    TotalChickens = g.Sum(x => x.Chickens), 
    TotalGoats = g.Sum(x => x.Goats)
}

将产生单个查询,并在数据库端进行求和,这比将整个表拉过来并在客户端进行求和要好得多。

关于c# - "Unzip"IEnumerable 在 C# 或最佳替代方案中动态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15690478/

相关文章:

c# - 在单元测试中验证 Autofac 注册

java - 给定素数分解,生成一个数的所有因数

vb.net - 列表框填充的优化

python - De Casteljau 算法忽略一个控制点

c# - linq查询从多个表中获取计数

c# - 我如何知道 XML 标签的索引

c# - "Must create DependencySource on same Thread as the DependencyObject"创建GridView时

c# - 从 VB 转换为 C#

c# - 如何使用 SharpZipLib 在 C# 中创建超过 7 GB 的 zip 文件?

c# - 使用 LINQ 的条件 Group By 语句