使用Linq仅查找在标志列表中具有所有匹配值的记录?

时间:2018-10-22 21:42:33

标签: c# linq

我有一个记录列表,每个主记录中都有一个0到许多标志的列表。我试图提出一个Linq查询,以仅带回与标志列表中所有标志匹配的记录。

var flags = new List<string>() {"flag1","flag5"}; 
//The flags list could also be empty in which case it should match records with no flags set.
var tbs = db.MyContents
.Select(a => new  {a.Id, FlagList=a.Flags.Select(f=>f.Name).ToList()})
.Where(f=>f.FlagList.Intersect(flags).Any());

上面的代码带回所有具有"flag1 ||flag5""flag1 && flag5"的记录。但是我想做的是只带回既有"flag1 && flag5"

的那些记录

有什么建议或想法吗?

3 个答案:

答案 0 :(得分:2)

您可以尝试将Except与NOT Any结合使用,以确保flags集合中的每个值都匹配。

var tbs = db.MyContents
           .Select(a => new { a.Id, FlagList = a.Flags.Select(f => f.Name) })
           .Where(f => !flags.Except(f.FlagList).Any());

编辑

我看到您在编辑问题,只需要在linq where中添加一些逻辑

var tbs = c.Select(a => new { a.Id, FlagList = a.Flags.Select(f => f.Name) })
               .Where(f => !flags.Except(f.FlagList).Any() && flags.Count() > 0 ||
                       flags.Count() == 0 && f.FlagList.Count() == 0);

答案 1 :(得分:1)

也许您可以将Where()是:

.Where(f=>f.FlagList.Intersect(flags).Count() == flags.Count());

答案 2 :(得分:0)

因此,您有一个Records序列,其中每个Record都有一个Flags序列。您还可以使用其他标志序列。

示例:

var oftherFlags = A B C
var records = record A with flags A B
              record B with flags A B C
              record C with flags   B C
              record D with flags A B C D
              record E with flags A A A A A B C
  

“我想提出一个Linq查询以带回与所有标志匹配的所有记录”

显然,记录B可以。记录A和C缺少一些记录;您要录制D吗?它具有所有标志,甚至还有更多标志。那是问题吗?那记录E呢?您忘记指定任何有关重复项的信息

让我们假设所有Flag序列都可能有重复,并且您不必担心重复。

因此以下内容将给出相同的结果

var otherFlags = A B C
var otherFlags = A B C C C C C

HashSet来营救!

IEnumerable<string> otherFlags = ...
var result = myRecords
    // put the flags in a HashSet, this removes duplicates
    .Select(record => new
    {
         Record = record,
         FlagSet = new HashSet<string>(record.Flags),
    })
    // keep only those elements where the FlagSet is a superset of otherFlags
    .Where(element => element.FlagSet.IsSuperSetOf(otherFlags)
    .Select(element => element.Record);

如果应该考虑重复项,那么如果otherFlags有两个A,而您只希望Records有两个A,则可以使用Enumerable.Except

var result = myRecords
    .Where(record => record.Flags    // from every record take the flags
         .Except(otherFlags)         // remove all otherFlags
         .Any());                    // keep the record if there are still flags left