确定2个项目列表的特定属性之间是否存在任何差异的最有效方法是什么?

时间:2015-10-07 13:55:30

标签: linq c#-4.0

在C#.NET 4.0中,我正在努力想出最有效的方法来确定2个项目列表的内容是否包含任何差异。

我不需要知道差异是什么,只是根据我的标准,列表是否不同,这是真是假。

我想要比较的2个列表包含FileInfo对象,我想只比较每个项目的FileInfo.Name和FileInfo.LastWriteTimeUtc属性。所有FileInfo项都用于位于同一目录中的文件,因此FileInfo.Name值将是唯一的。

总结一下,我正在寻找以下标准的单个布尔结果:

  1. ListA是否包含FileInfo.Name不在ListB中的任何项目?
  2. ListB是否包含FileInfo.Name中不在ListA中的任何项目?
  3. 对于两个列表中具有相同FileInfo.Name的项目,FileInfo.LastWriteTimeUtc值是否不同?
  4. 谢谢,

    凯尔

2 个答案:

答案 0 :(得分:1)

我会使用自定义IEqualityComparer<FileInfo>执行此任务:

public class FileNameAndLastWriteTimeUtcComparer : IEqualityComparer<FileInfo>
{
    public bool Equals(FileInfo x, FileInfo y)
    {
        if(Object.ReferenceEquals(x, y)) return true;
        if (x == null || y == null) return false;
        return x.FullName.Equals(y.FullName) && x.LastWriteTimeUtc.Equals(y.LastWriteTimeUtc);
    }

    public int GetHashCode(FileInfo fi)
    {
        unchecked // Overflow is fine, just wrap
        {
            int hash = 17;
            hash = hash * 23 + fi.FullName.GetHashCode();
            hash = hash * 23 + fi.LastWriteTimeUtc.GetHashCode();
            return hash;
        }
    }
}

现在,您可以使用HashSet<FileInfo>与此比较器和HashSet<T>.SetEquals

var comparer = new FileNameAndLastWriteTimeUtcComparer();
var uniqueFiles1 = new HashSet<FileInfo>(list1, comparer);
bool anyDifferences = !uniqueFiles1.SetEquals(list2);

请注意,我使用的是FileInfo.FullName而不是Name,因为名字根本不具备。

旁注:另一个优点是您可以将此比较器用于许多LINQ方法,例如GroupByExceptIntersectDistinct

答案 1 :(得分:0)

这不是最有效的方法(可能在快速和肮脏的类别中排名为5分中的四分之一):

var comparableListA = ListA.Select(a => 
    new { Name = a.Name, LastWrite = a.LastWriteTimeUtc, Object = a});
var comparableListB = ListB.Select(b => 
    new { Name = b.Name, LastWrite = b.LastWriteTimeUtc, Object = b});

var diffList = comparableListA.Except(comparableListB);

var youHaveDiff = diffList.Any();

<强>解释
匿名类通过属性值进行比较,这是您要做的事情,这导致我考虑沿着这些线进行LINQ投影。

<强> P.S。
你应该仔细检查语法,我只是在没有编译器的情况下解决这个问题。