【问题标题】:Compare Collection of Collections比较集合的集合
【发布时间】:2014-09-24 14:05:41
【问题描述】:

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

我还能做些什么来比较这两个集合?

【问题讨论】:

  • 实现IEquatable&lt;T&gt;或创建IEqualityComparer&lt;T&gt;,其中TFolder

标签: c# list compare


【解决方案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实现

【讨论】:

  • 我没有让你的解决方案起作用,但我已经自己解决了
【解决方案2】:

我自己解决了这个问题:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-04
    • 2018-11-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多