将递延的IEnumerable 分成两个序列,而无需重新评估?

| 我有一种方法需要处理输入的命令序列,然后根据结果的某些属性将结果分成不同的存储桶。例如:
class Pets
{
    public IEnumerable<Cat> Cats { get; set; }
    public IEnumerable<Dog> Dogs { get; set; }
}

Pets GetPets(IEnumerable<PetRequest> requests) { ... }
基础模型完全能够一次处理
PetRequest
元素的整个序列,并且
PetRequest
大多是通用信息,例如ID,因此尝试在输入处拆分请求没有任何意义。但是提供程序实际上并没有提供
Cat
Dog
实例,只是一个通用的数据结构:
class PetProvider
{
    IEnumerable<PetData> GetPets(IEnumerable<PetRequest> requests)
    {
        return HandleAllRequests(requests);
    }
}
我将响应类型命名为
PetData
而不是
Pet
,以明确表明它不是
Cat
Dog
的超类-换句话说,转换为
Cat
Dog
是映射过程。要记住的另一件事是12英镑很贵,例如数据库查询,所以我真的不想重复它,并且我宁愿避免使用
ToArray()
之类的东西将结果缓存在内存中,因为可能有成千上万的结果(我有很多宠物) 。 到目前为止,我已经能够将这种笨拙的技巧归纳在一起:
Pets GetPets(IEnumerable<PetRequest> requests)
{
    var data = petProvider.GetPets(requests);
    var dataGroups = 
        from d in data
        group d by d.Sound into g
        select new { Sound = g.Key, PetData = g };
    IEnumerable<Cat> cats = null;
    IEnumerable<Dog> dogs = null;
    foreach (var g in dataGroups)
        if (g.Sound == \"Bark\")
            dogs = g.PetData.Select(d => ConvertDog(d));
        else if (g.Sound == \"Meow\")
            cats = g.PetData.Select(d => ConvertCat(d));
    return new Pets { Cats = cats, Dogs = dogs };
}
从某种意义上说,这不会使ѭ6的结果被枚举两次,但它在技术上是可行的,但是它有两个主要问题: 在代码上看起来像一个巨大的丘疹。它散发出我们在LINQ之前的框架2.0中一直必须使用的可怕的命令式风格。 最终这是一个完全没有意义的练习,因为
GroupBy
方法只是将所有结果缓存在内存中,这意味着我真的比没有懒惰并先做了
ToList()
更好。附加了一些谓词。 因此,重申一下这个问题: 是否可以将一个延迟的ѭ18实例拆分为两个
IEnumerable<?>
实例,而无需执行任何急切的评估,将结果缓存在内存中或不必第二次重新评估原始的
IEnumerable<T>
? 基本上,这将与“ 21”运算相反。 .NET框架中还没有一个事实,这强烈表明这甚至不可能实现,但是我认为无论如何也不会受到伤害。 附言请不要告诉我创建
Pet
超类,而只返回
IEnumerable<Pet>
。我使用
Cat
Dog
作为有趣的示例,但实际上结果类型更像
Item
Error
-它们都从相同的通用数据派生,但根本没有共同点。     
已邀请:
        从根本上说,不。想象一下是否有可能。然后考虑如果我这样做会发生什么:
foreach (Cat cat in pets.Cats)
{
    ...
}

foreach (Dog dog in pets.Dogs)
{
    ...
}
那需要先处理所有的猫,然后处理所有的狗...所以如果第一个元素是
Dog
,那么原始序列会发生什么?它要么必须缓存它,要么跳过它-它不能返回它,因为我们仍然要30英镑。 您可以实现仅缓存所需数量的东西,但这很可能是一个序列的全部,因为典型用法是完全评估一个或另一个序列。 如果有可能,您真的只想在取宠物时处理宠物(无论是猫还是狗)。提供
Action<Cat>
Action<Pet>
并为每个项目执行正确的处理程序是否可行?     
        乔恩所说的话(我敢肯定我是百万分之一的人)。 我可能只是去上学了,要做:
List<Cat> cats = new List<Cat>();
List<Dog> dog = new List<Dog>();

foreach(var pet in data)
{
   if (g.Sound == \"Bark\")
     dogs.Add(ConvertDog(pet));
   else if (pet.Sound == \"Meow\")
     cats.Add(ConvertCat(pet));
}
但是我意识到这并不是您想要做的-但是您确实说过重新评估-而且只评估​​一次:)     

要回复问题请先登录注册