具有特殊组分组和过滤的LINQ查询

时间:2010-11-09 15:47:42

标签: c# .net linq

我有一个班级......

class Document
{
    public int GroupID  { get; set; }
    public bool Valid { get; set; }
    // more
}

...以及实例列表:IEnumerable<Document> documents。在通过此列表逐个对象运行的第一步中,这些文档已经过验证,这意味着:对于某些对象,属性Valid将为true,对于列表中的其他对象,属性为false

现在我需要做第二步:

  • 如果每个文档组至少有一个文档(由具有相同GroupID的所有文档定义),则标记Validfalse,然后将Valid设置为{{1}对于该组的所有文件。

为此,我创建了以下代码片段:

false

我相信,这样做符合我的要求(但直到现在我都没有测试过),但效率不高。

问题:是否有办法改进此代码,尤其是将外部foreach循环中的var q = from d in documents group d by d.GroupID; // q is now of type IEnumerable<IGrouping<int, Document>> foreach (var dg in q) // dg = "document group", of type IGrouping<int, Document> { if (dg.Any(d => !d.Valid)) { foreach (var d in dg) d.Valid = false; } } 方法的语义“以某种方式”移动到初始LINQ查询中,以便Any仅表示至少有一个无效文件的团体? (另外,我显然对只有一个元素的组不感兴趣,所以这些组也可以被过滤掉。)

提前感谢您的建议!

2 个答案:

答案 0 :(得分:5)

我认为这可以满足您的需求:

var q = from d in documents
        group d by d.GroupID into g
        where g.Count() > 1 && g.Any(d => !d.Valid)
        select g;

foreach (var dg in q)
{
    foreach (var d in dg)
    {
        d.Valid = false;
    }
}

流利语法的顶部部分如下:

var q = documents.GroupBy(d => d.GroupID)
            .Where(g => g.Count() > 1 && g.Any(d => !d.Valid));

答案 1 :(得分:1)

如果您只是尝试将其中一个文档设置为无效,则尝试将有效标记设置为false,您可以尝试抓取无效的GroupId列表,然后设置其共享组的所有文档他们无效。示例代码如下:

//Find the invalid GroupIds.
var invalidIds = documents.Where(d => !d.IsValid).Select(p => p.GroupId).Distinct();

//invalidIds now holds the bad groupIds.
//So we can find out if each document's GroupId is an invalid one, and if it is, mark it as invalid.
documents.Where(d => invalidIds.Contains(d.GroupId)).ToList().ForEach(p => p.IsValid = false);

希望这有帮助。