代码之家  ›  专栏  ›  技术社区  ›  Slauma

具有特殊组分组和筛选功能的LINQ查询

  •  5
  • Slauma  · 技术社区  · 14 年前

    我有个班……

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

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

    现在,在第二步中,我必须执行以下操作:

    • 如果每个文档组至少有一个文档(由具有相同文档的所有文档定义) GroupID )国旗 有效的 然后设置 有效的 集团所有文件。

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

    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;
        }
    }
    

    我相信,这是我想要的(虽然我直到现在才测试它),但效率不是很高。

    问题:是否有方法改进此代码,特别是移动 Any 方法在外部foreach循环中“莫名其妙地”进入初始Linq查询,以便 q 仅表示至少有一个无效文档的组?(显然,我对只有一个元素的组不感兴趣,因此也可以过滤掉这些组。)

    感谢您提前提出建议!

    2 回复  |  直到 14 年前
        1
  •  5
  •   kevev22    14 年前

    我认为这是你想要的:

    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));
    
        2
  •  1
  •   Jeffrey Lott    14 年前

    如果您只是试图将有效标志设置为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);
    

    希望这有帮助。