我需要比较两个列表,每个列表包含大约 60,000 个对象。 最有效的方法是什么? 我想选择源列表中不存在的目标列表中的所有项目。
我正在创建一个同步应用程序,其中 c# 扫描目录并将每个文件的属性放在列表中。 因此,源目录有一个列表,目标目录有一个列表。然后,我不会复制所有文件,而是比较列表,看看哪些文件不同。如果两个列表都有相同的文件,那么我不会复制该文件。这是我使用的 Linq 查询,它在扫描小文件夹时有效,但在扫描大文件夹时无效。
// s.linst is the list of the source files
// d.list is the list of the files contained in the destination folder
var q = from a in s.lstFiles
from b in d.lstFiles
where
a.compareName == b.compareName &&
a.size == b.size &&
a.dateCreated == b.dateCreated
select a;
// create a list to hold the items that are the same later select the outer join
List<Classes.MyPathInfo.MyFile> tempList = new List<Classes.MyPathInfo.MyFile>();
foreach (Classes.MyPathInfo.MyFile file in q)
{
tempList.Add(file);
}
我不知道为什么这个查询需要很长时间。还有其他事情我可以利用。例如,我知道如果源文件与目标文件匹配,则不可能与该文件有另一个副本,因为不可能必须具有相同名称和相同路径的文件名。
为类型创建一个相等比较器,然后可以使用它来有效地比较集合:
public class MyFileComparer : IEqualityComparer<MyFile> {
public bool Equals(MyFile a, MyFile b) {
return
a.compareName == b.compareName &&
a.size == b.size &&
a.dateCreated == b.dateCreated;
}
public int GetHashCode(MyFile a) {
return
(a.compareName.GetHashCode() * 251 + a.size.GetHashCode()) * 251 +
a.dateCreated.GetHashCode();
}
}
现在,您可以将它与 Intersect
等方法一起使用,以获取两个列表中存在的所有项目,或者Except
获取一个列表中存在但另一个列表中不存在的所有项目:
List<MyFile> tempList =
s.lstFiles.Intersect(d.lstFiles, new MyFileComparer()).ToList();
由于这些方法可以使用哈希代码将项目划分为存储桶,因此与联接相比,需要完成的比较要少得多,联接必须将一个列表中的所有项目与另一个列表中的所有项目进行比较。
LINQ 有一个用于此目的的Except()
方法。你可以只使用a.Except(b);
Except()
并阅读有关使用 linq 进行设置操作和使用 HashSet
进行设置操作的更多信息。