我需要比较两个列表,其中每个列表包含大约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);
}
我不知道为什么这个查询需要永远。还有其他我可以利用的东西。例如,我知道如果源文件与目标文件匹配,则不可能与该文件有另一个副本,因为不可能具有相同名称和相同路径的文件名。
答案 0 :(得分:4)
LINQ有一个Except()
方法用于此目的。您可以使用a.Except(b);
答案 1 :(得分:4)
为该类型创建一个相等比较器,然后您可以使用它来有效地比较这些集:
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();
由于方法可以使用哈希码将项目划分为桶,因此与需要将一个列表中的所有项目与另一个列表中的所有项目进行比较的连接相比,需要进行的比较要少得多。
答案 2 :(得分:1)
使用Except()
并详细了解set operations with linq和set operations with HashSet
。