繁体   English   中英

检查每个包含另一个对象的对象的集合是否包含List的所有值 <string> 通过LINQ

[英]check if collection of objects where each contain another collection of objects contain all values of List<string> via LINQ

我有一个对象集合,其中每个对象都包含另一个对象集合。 我需要找出最快的方法来检查它是否包含List<string>所有值。

这是一个例子:

class Video {        
  List<Tag> Tags; 
}

class Tag{
  public Tag (string name){
    Name = name;
  }

  string Name;
}

List<string> selectedTags = new List<string>();
selectedTags.Add("Foo");
selectedTags.Add("Moo");
selectedTags.Add("Boo");

List<Video> videos = new List<Video>();

// Case A
Video videoA = new Video();
videoA.Tags = new List<Tag>();
videoA.Tags.Add(new Tag("Foo"));
videoA.Tags.Add(new Tag("Moo"));
videos.Add(videoA);  

LINQ 不应选择videoA ,因为它不包含所有标签。

// Case B
Video videoB = new Video();
videoB.Tags = new List<Tag>();
videoB.Tags.Add(new Tag("Foo"));
videoB.Tags.Add(new Tag("Moo"));
videoB.Tags.Add(new Tag("Boo"));
videos.Add(videoB);  

videoB 应该选择videoB ,因为它包含所有标签。

我用foreach循环进行了尝试,但是它太慢了,因此我正在寻找LINQ解决方案。

foreach (Video video in videos) {
  if (video.Tags.Count() > 0) {
    bool containAllTags = true;
    foreach (string tagToFind in selectedTags) {
      bool tagFound = false;
      foreach (Tag tagItem in video.Tags) {
        if (tagToFind == tagItem.Name)
          tagFound = true;
      }
      if (!tagFound)
        containAllTags = false;
    }
    if (containAllTags)
      result.Add(videoItem);
  }
}

生成的LINQ应该如下所示:

IEnumerable<Video> = from vid in videos
                     where vid.Tags.( ..I dont know.. )
                     select vid;

我试着用几种方法.Any.All ,等等。但我不能找到解决办法,我不能用.Intersect因为一个是一个List的字符串,另一个是一个List对象。 请注意,在正式版中, VideoTag元素具有更多属性。

使用当前代码,您在逻辑上需要:

IEnumerable<Video> result = from vid in videos
                            where selectedTags.All(tag =>
                                     vid.Tags.Any(t => t.Name == tag))
                            select vid;

或等效地:

var result = videos.Where(vid => selectedTags.All(tag => 
                                      vid.Tags.Any(t => t.Name == tag)));

当然,这是假定您已将Tag.NameVideo.Tags公开-理想情况下是作为属性而不是作为字段。

请注意,我们是如何针对selectedTags调用All ,因为(假设我已正确阅读您的要求)重要的是,视频中必须包含所有选定的标签-选择所有视频的标签并不重要。

现在,如果您要检查很多标签并且每个视频有很多标签,那可能会比较慢。

但是,知道如何优化它实际上将取决于其他一些选择:

  • 如果标记的顺序不重要,是否可以将Video.Tags更改为集合而不是列表?
  • 您是否一直在浏览同一组视频,以便可以进行一些预处理?
  • 可用标签总数大吗? 每个视频的标签数量如何? 所选标签的数量如何?

另外,您可以将每个视频投影到其“标签列表”,然后检查所选视频集中是否有未包含的视频:

var result = videos.Where(vid => !selectedTags.Except(vid.Tags.Select(t => t.Name))
                                              .Any());

暂无
暂无

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

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