C# 检查每个包含另一个对象集合的对象集合是否包含列表的所有值<;字符串>;林克大道
我有一个对象集合,其中每个对象包含另一个对象集合。我需要找出最快的方法来检查它是否包含C# 检查每个包含另一个对象集合的对象集合是否包含列表的所有值<;字符串>;林克大道,c#,linq,C#,Linq,我有一个对象集合,其中每个对象包含另一个对象集合。我需要找出最快的方法来检查它是否包含List的所有值 以下是一个例子: class Video { List<Tag> Tags; } class Tag{ public Tag (string name){ Name = name; } string Name; } List<string> selectedTags = new List<string>();
List
的所有值
以下是一个例子:
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);
videoB
应该由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);
我尝试了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;
IEnumerable=来自视频中的视频
视频标签在哪里(我不知道)
选择视频;
我用
.Any
,.All
等尝试了几种方法。。但是我找不到解决方案,也不能使用.Intersect
,因为一个是字符串的列表
,另一个是对象的列表。请注意,在生产版本中,Video
和Tag
元素具有更多属性。对于当前代码,您在逻辑上需要:
这是假设您已经公开了Tag.Name
和Video.Tags
,当然,最好是作为属性而不是字段
请注意,我们是如何针对selectedTags
调用All
,因为(假设我正确阅读了您的要求)所有选定的标记都出现在视频中很重要-选择所有视频的标记并不重要
如果你有很多标签要检查,而且每个视频都有很多标签,那么这可能会比较慢
然而,知道如何优化它实际上取决于其他一些选择:
- 如果标签的顺序不重要,您能否将
Video.tags
更改为集合而不是列表
- 您是否总是浏览同一组视频,以便执行一些预处理
- 可用标签的总数是否很大?每个视频的标签数量是多少?所选标签的数量如何
或者,您可以将每个视频投影到其“标签列表”中,并检查所选集合中是否有不在视频集合中的任何视频:
var result = videos.Where(vid => !selectedTags.Except(vid.Tags.Select(t => t.Name))
.Any());
标签的顺序重要吗?或者你是把它们当作集合来处理吗?不,顺序并不重要,因为vid.tags.
可能需要投影,因为selectedTags
是一个列表
,而内部集合是一个列表
(因此当前的包含的将不起作用)。我不这么认为,因为在“selectedTags.All(tag”>“tag”是字符串,但此处的“vid.Tags.Contains(tag))”>“tag”是字符串“必须是标记对象,因此它不能等于字符串。如果视频有列表标签,你的解决方案就可以了。如果我是,请纠正我wrong@OselMikoD伊沃鲁贝克:啊,我没有注意到这一点。我愚蠢地期望名为selectedTags
的变量是列表
,而不是列表
。你能修改你的代码使数据模型更加一致吗?@AdamHouldsworth:我已经修改了我的答案,这样它就可以与当前的设置一起工作,但我仍然认为避免一个字符串集合和一个标记
对象集合会更干净。一致性使代码更清晰:)我认为从问题名称和描述可以明显看出,我需要将其与列表进行比较。。。
var result = videos.Where(vid => selectedTags.All(tag =>
vid.Tags.Any(t => t.Name == tag)));
var result = videos.Where(vid => !selectedTags.Except(vid.Tags.Select(t => t.Name))
.Any());