比较集合的集合
本文关键字:集合 比较 | 更新日期: 2023-09-27 18:24:09
我有一个名为Folder的类,它看起来像
public class Folder
{
public int Id{get;set;}
public string Titel{get;set;}
public List<Folder> Folders{get;set;}
public List<Document> Documents{get;set;}
}
我每10秒钟从数据库中得到一个文件夹列表。现在我需要将新的文件夹列表与内存中已有的文件夹列表进行比较。
最好的方法是什么?
我的第一个方法是:
if(currentFolders.GetHashCode() != newFolders.GetHashCode())
{
// Work with changed data
}
此外,如果两个集合相同,我会得到不同的哈希代码。
我的第二次尝试是将类标记为[Serializable]
,并将两个列表序列化为Byte[]
byte[] b1, b2;
using (var m1 = new MemoryStream())
{
using (var m2 = new MemoryStream())
{
var binaryFormatter = new BinaryFormatter();
binaryFormatter.Serialize(m1, newFolders);
b1 = m1.ToArray();
binaryFormatter.Serialize(m2, currentFolders);
b2 = m2.ToArray();
}
}
不幸的是,Folder
-class
是通过Linq2SQL自动生成的,所以我不能轻易地将其标记为Serializable
我还能做些什么来比较这两个系列?
提供:
- Document类只有一个Name属性
- 您的集合不包含null实例
- 如果相等,则比较应返回true,否则返回false
您可以执行以下操作:
public bool Compare(Document expected, Document actual)
{
return (actual.Name == expected.Name);
}
public bool Compare(Folder expected, Folder actual)
{
return (actual.Id == expected.Id) &&
(actual.Titel == expected.Titel) &&
Compare(actual.Documents, expected.Documents, Compare) &&
Compare(actual.Folders, expected.Folders, Compare);
}
public bool Compare<T>(ICollection<T> expected, ICollection<T> actual,
Func<T, T, bool> comparer)
{
return (actual.Count == expected.Count) &&
actual.Zip(expected, (left, right) => comparer(left, right)).
All(comparison => comparison);
}
可以通过以下方式使用:
List<Folder> previous = ...
List<Folder> current = /* Get from DB */
if (!Compare(previous, current))
{
// Something changed
}
您还可以实现IEqualityComparer实现
我自己用解决了这个问题
internal class FolderComparer
{
internal bool AreCollectionsEqual(IEnumerable<Folder> folderList1, IEnumerable<Folder> folderList2)
{
var flatFolderList1 = BuildFlatFolderList(folderList1);
var flatFolderList2 = BuildFlatFolderList(folderList2);
return !flatFolderList1.Except(flatFolderList2).Any();
}
private IEnumerable<int> BuildFlatFolderList(IEnumerable<Folder> folders)
{
List<int> folderIdList = new List<int>();
DoBuildFlatFolderList(folders, folderIdList);
return folderIdList;
}
private void DoBuildFlatFolderList(IEnumerable<Folder> folders, ICollection<int> resultList)
{
foreach (var folder in folders)
{
resultList.Add(folder.Id);
DoBuildFlatFolderList(folder.Folders.ToList(), resultList);
}
}
}