2014-03-26 107 views
-1

我有一个对象集合,其中每个对象都包含另一个对象集合。我需要找出最快的方法来检查它是否包含所有值List<string>检查每个包含另一个对象集合的对象集合是否包含通过LINQ的所有列表值<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); 

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

// 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可以通过LINQ,因为它包含的所有标签中选择。

我试过用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元素有更多的属性。

+0

是标签的顺序重要还是你将这些视为集合? –

+0

没有顺序并不重要 –

回答

3

以您目前的代码,你逻辑想:

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公众,当然 - 理想的性质而不是字段。

注意我们如何调用AllselectedTags,如(假设我已经正确地读出你的要求)是很重要的,所有选定的标签出现在视频 - 所有视频的标签选择它重要。

现在这可能会比较慢,如果你有很多标签要检查和每个视频有很多标签。

然而,知道如何优化它真的会依赖于一些其他的选择:

  • 如果标签的顺序并不重要,你可以改变Video.Tags是一个集而不是一个列表?
  • 你是否总是在浏览同一组视频,所以你可以执行一些预处理?
  • 标签总数是否可用很大?每个视频的标签数量如何?选定标签的数量呢?

或者,您可以项目中的每个视频,它的“标签列表”,并检查是否有任何所选的一组不属于视频的设置:

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

的'vid.Tags.'可能需要投影,因为'selectedTags'是下降的'名单'而内集合是一个'清单'(所以目前'Contains'赢得”工作)。 –

+0

我不这么认为,因为“selectedTags.All(标签”>“标签”是字符串,但在这里“vid.Tags.Contains(标签))”>“标签”必须是标签对象,因此它不能等于字符串。如果视频有列表标签,您的解决方案将工作。纠正我,如果我错了 –

+0

@OselMikoDřevorubec:啊,我没有注意到这一点。我愚蠢地期望一个名为'selectedTags'的变量是'List '而不是'List '。你能修复你的代码来使数据模型更加一致吗? –

相关问题