简体   繁体   English

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

[英]A LINQ query with grouping and filtering of special groups

I have a class... 我有课...

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

... and a list of instances: IEnumerable<Document> documents . ...以及实例列表: IEnumerable<Document> documents In a first step which runs object by object through this list those documents have been validated, which means: the property Valid will be true for some objects and false for other objects in the list. 在通过该列表逐个对象运行的第一步中,已验证了那些文档,这意味着:属性Valid对于列表中的某些对象为true ,而对于其他对象为false

Now in a second step I have to do the following: 现在,在第二步中,我必须执行以下操作:

  • If for at least one document per document group (defined by all documents with the same GroupID ) the flag Valid is false then set Valid to false for all documents of the group. 如果每个文档组至少有一个文档(由具有相同GroupID的所有文档定义),则标志Validfalse然后将该组中的所有文档的Valid设置为false

To do this I have created so far the following code fragment: 为此,到目前为止,我已经创建了以下代码片段:

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

I believe, this does what I want (I didn't test it until now, though) but not very efficiently. 我相信,这确实可以实现我想要的功能(不过直到现在我还没有对其进行测试),但是效率却不是很高。

Question: Is there a way to improve this code, especially to move the semantics of the Any method in the outer foreach loop "somehow" into the initial LINQ query, so that q only represents the groups which have at least one invalid document? 问题:是否有方法可以改进此代码,特别是将外部foreach循环中的Any方法的语义“以某种方式”移至初始LINQ查询中,以便q仅表示具有至少一个无效文档的组? (Also I am obviously not interested in groups which have only one element, so those groups could be filtered out as well.) (另外,我显然对仅包含一个元素的组不感兴趣,因此也可以将这些组过滤掉。)

Thank you for suggestions in advance! 预先感谢您的建议!

I think this does what you want: 我认为这符合您的要求:

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

The top part in fluent syntax would look like: 流利的语法的顶部看起来像:

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

If you're just trying to set the Valid flag to false if one of the documents is not Valid, you could try grabbing the list of the GroupId's who are not valid and then set all of the documents whose share a group with them to be invalid. 如果您只是试图在其中一个文档无效时将Valid标志设置为false,则可以尝试获取无效的GroupId列表,然后将与它们共享一个组的所有文档设置为无效。 Sample code as follows: 示例代码如下:

//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);

Hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM