经过大量的谷歌搜索和代码实验,我被一个复杂的 C# LINQ-to-objects 问题难住了,在 SQL 中,使用一对 ROW_NUMBER()...PARTITION BY 函数和一个或两个子查询很容易解决这个问题。
换句话说,这就是我在代码中尝试做的事情——基本要求是从列表中删除重复的文档:
- 首先,按 (Document.Title, Document.SourceId) 对列表进行分组,假设(简化的)类定义如下:
类文件 { 字符串标题; 整数源ID;// 源优先(ID=1 优于 ID=2) }
-
在该组中,为每个文档分配一个索引(例如,索引 0 == 此来源中具有此标题的第一个文档,索引 1 = 此来源中具有此标题的第 2 个文档等)。我喜欢 SQL 中的 ROW_NUMBER() 等价物!
- 现在按 (Document.Title, Index) 分组,其中 Index 是在步骤 #2 中计算的。对于每个组,仅返回一个文档:具有最低 Document.SourceId 的文档。
第 1 步很简单(例如 codepronet.blogspot.com/2009/01/group-by-in-linq.html),但我对第 2 步和第 3 步感到困惑。我似乎无法构建一个无红色曲线的 C# LINQ 查询来解决所有三个步骤。
Anders Heilsberg 在此线程上的帖子是我认为如果我能正确使用语法,那么上面的步骤 #2 和 #3 的答案。
我宁愿避免使用外部局部变量来进行索引计算,如 slodge.blogspot.com/2009/01/adding-row-number-using-linq-to-objects.html 上所建议的那样,因为该解决方案会中断如果外部变量被修改。
最佳情况下,可以先完成按标题分组的步骤,因此“内部”分组(首先按 Source 计算索引,然后按 Index 过滤重复项)可以对每个“按标题”中的少量对象进行操作组,因为每个按标题组中的文档数通常低于 100。我真的不想要 N 2解决方案!
我当然可以使用嵌套的 foreach 循环来解决这个问题,但这似乎是使用 LINQ 应该很简单的问题。
有任何想法吗?