比较收藏集

时间:2014-09-24 14:05:42

标签: c# list compare

我有一个名为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

我还可以做些什么来比较这两个系列?

2 个答案:

答案 0 :(得分:1)

本发明提供:

  • 您的Document类只有一个Name属性
  • 您的馆藏不包含空实例
  • 您的比较应该在相等的情况下返回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实施

答案 1 :(得分:0)

我自己解决了这个问题:

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);
        }    
    }
}