C# 冒充LINQ的iGroup
假设您有一个大型数据集,该数据集可能会被数据集元素的特定条件过滤,也可能不会被过滤,而这些数据集元素可能需要大量计算。在未过滤的情况下,元素按该条件的值分组-该条件计算一次 但是,在已进行筛选的情况下,尽管后续代码仍希望看到C# 冒充LINQ的iGroup,c#,linq,optimization,C#,Linq,Optimization,假设您有一个大型数据集,该数据集可能会被数据集元素的特定条件过滤,也可能不会被过滤,而这些数据集元素可能需要大量计算。在未过滤的情况下,元素按该条件的值分组-该条件计算一次 但是,在已进行筛选的情况下,尽管后续代码仍希望看到IEnumerable集合,但执行GroupBy操作将导致对每个元素再次评估条件是没有意义的。相反,我希望能够通过适当地包装过滤结果来创建一个IEnumerable,从而避免对条件进行另一次评估 除了实现我自己的类来提供I分组接口之外,还有其他方法可以实现这种优化吗?是否有现
IEnumerable
集合,但执行GroupBy
操作将导致对每个元素再次评估条件是没有意义的。相反,我希望能够通过适当地包装过滤结果来创建一个IEnumerable
,从而避免对条件进行另一次评估
除了实现我自己的类来提供
I分组
接口之外,还有其他方法可以实现这种优化吗?是否有现有的LINQ方法支持这一点,从而得到IEnumerable
结果?还有其他我没有考虑过的方法吗?将结果放入查找中,然后在其余时间使用它怎么样
var lookup = data.ToLookUp(i => Foo(i));
条件计算一次
我希望那些钥匙还在附近的某个地方
如果数据的结构如下所示:
public class CustomGroup<T, U>
{
T Key {get;set;}
IEnumerable<U> GroupMembers {get;set}
}
var result = customGroups
.SelectMany(cg => cg.GroupMembers, (cg, z) => new {Key = cg.Key, Value = z})
.GroupBy(x => x.Key, x => x.Value)
受此启发,我想出了一个简单的解决方案。这么简单,我不知道我怎么会错过它
为了执行过滤,我显然需要知道过滤条件的值。因此,给定一个条件,c
,我可以将过滤后的列表投影为:
filteredList.GroupBy(x => c)
这样可以避免对元素(由x
表示)的属性进行任何重新计算
我意识到的另一个解决方案是在执行过滤之前反转查询的顺序并执行分组。这也意味着只对条件求值一次,尽管它会不必要地分配我以后不会使用的分组。不幸的是,查找没有实现IEnumerable。我想我可以将过滤组和非过滤组都放入查找中,但我希望避免对过滤列表进行额外处理,同时避免对后续代码进行任何更改。我将研究它并发回。我不能保证键仍然存在——这是一个使用我没有编写的结构的复杂查询,因此不能依赖于任何类型的缓存。然而,你提出了一个我认为可行的解决方案——现在看来很明显。我应该补充一点,这确实意味着通过一个循环对所有项目进行分组,如果可以的话,我仍然希望避免这种情况。我仍然可以创建自己的分组类,以便避免这种情况。