比较两个包含大量对象的列表(第三部分)“这些对象具有不同的类型”
我怎样才能加快这个 linq 查询的速度?
这需要很长时间,当我在列表中放置很多对象时,我会遇到内存异常。
List<DirectoryInfo> directoriesThatWillBeCreated = new List<DirectoryInfo>();
// some code to fill the list
// ..
// ..
List<FileInfo> FilesThatWillBeCopied = new List<FileInfo>();
// some code to fill the list
//....
directoriesThatWillBeCreated = (from a in FilesThatWillBeCopied
from b in directoriesThatWillBeCreated
where a.FullName.Contains(b.FullName)
select b).ToList();
How could I speed up this linq query?
It takes a long time and when I place a lot of objects in the list I get a memory exception.
List<DirectoryInfo> directoriesThatWillBeCreated = new List<DirectoryInfo>();
// some code to fill the list
// ..
// ..
List<FileInfo> FilesThatWillBeCopied = new List<FileInfo>();
// some code to fill the list
//....
directoriesThatWillBeCreated = (from a in FilesThatWillBeCopied
from b in directoriesThatWillBeCreated
where a.FullName.Contains(b.FullName)
select b).ToList();
I hope I can do something like previous solution but I don't know how to do that when dealing with different types of objects. Do I have to create a new class then convert all the FileInfo and DirectoryInfo objects to that class then perform the query? Moreover FileInfo and DirectoryInfo classes are sealed and I cannot inherit from them therefore I'll have to create a new class and that will be not to efficient. At least that will be more efficient than that query because that query takes forever.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以做的一件事是将 包含 更改为 开始。如果匹配失败,
StartsWith
会更快失败。但这并不是一个完整的解决方案。如果
FilesThatWillBeCopied
有 M 个项目,而directoriesThatWillBeCreated
有 N 个元素,那么您的查询将处理 MxN 字符串比较。另一种选择
尝试另一种优化,首先遍历
directoriesThatWillBeCreated
,然后选择与FilesThatWillBeCopied
中的任何FileInfo
匹配的那些。通过检查是否有任何匹配,一旦找到匹配,您就可以停止测试文件。可以这样做:(警告,记事本代码如下)One thing you could do is change the Contains to a StartsWith.
StartsWith
will fail faster in the event of a failed match.This isn't a complete solution, though. If
FilesThatWillBeCopied
has M items anddirectoriesThatWillBeCreated
has N elements, then your query is going to process MxN string comparisons.Another Option
Another optimization to try, iterate through
directoriesThatWillBeCreated
first, then select those that match anyFileInfo
inFilesThatWillBeCopied
. By checking if any match, you could break out of testing the files once a match is found. That could be done like this: (warning, notepad code follows)它很慢,因为代码在目录列表中对每个文件进行线性搜索。试试这个:
您可能需要稍微尝试一下语法,但希望您明白这一点。
It's slow because the code does linear search in directory list for each file. Try this:
You may need to play with the syntax a little bit but hopefully you see the point.
我建议使用
HashSet
进行比较,但不幸的是,DirectoryInfo
没有实现适当的相等比较,因此必须使用字符串。 (另一种选择是实现您自己的IComparer
。)此外,您应该在名称上使用StringComparer.InvariantCultureIgnoreCase
,除非您确定两个集合具有相同的内容案件。此解决方案根本不使用 LINQ,但当您追求性能并且最直接的 LINQ 解决方案太慢时,通常会出现这种情况。
I would suggest using
HashSet<DirectoryInfo>
for comparisons, but unfortunately,DirectoryInfo
doesn't have proper equality comparisons implemented, so strings will have to do. (Another option would be to implement your ownIComparer<DirectoryInfo>
.) Also, you should useStringComparer.InvariantCultureIgnoreCase
on the names unless you are sure that both collections have the same case.This solution doesn't use LINQ at all, but that's often the case when you're after performance and the most straight-forward LINQ solution is too slow.