一尘不染

比较两个列表的差异

c#

我想就如何最好地编写一个通用函数来比较两个列表提供一些反馈。列表包含类对象,我们要遍历一个列表,在第二个列表中查找相同项目并报告任何差异。

我们已经有一个比较类的方法,因此我们需要有关如何从两个列表中提供该方法的反馈(如下所示)。

例如,假设我们有一个简单的“ Employee”类,它具有三个属性,即Name,ID和Department。我们要报告List和另一个List之间的差异。

注意:
两个列表将始终包含相同数量的项目。

如上所述,我们有一个通用方法可用来比较两个类,如何将这种方法结合起来以迎合Lists的需要,即从另一种方法循环遍历List并将这些类提供给通用方法....但是我们如何在第二个List中找到等效的类传递给下面的方法;

public static string CompareTwoClass_ReturnDifferences<T1, T2>(T1 Orig, T2 Dest)
    where T1 : class
    where T2 : class
{
    // Instantiate if necessary
    if (Dest == null) throw new ArgumentNullException("Dest", "Destination class must first be instantiated.");

    var Differences = CoreFormat.StringNoCharacters;

    // Loop through each property in the destination  
    foreach (var DestProp in Dest.GetType().GetProperties())
    {
        // Find the matching property in the Orig class and compare
        foreach (var OrigProp in Orig.GetType().GetProperties())
        {

            if (OrigProp.Name != DestProp.Name || OrigProp.PropertyType != DestProp.PropertyType) continue;
            if (OrigProp.GetValue(Orig, null).ToString() != DestProp.GetValue(Dest, null).ToString())
                Differences = Differences == CoreFormat.StringNoCharacters 
                    ? string.Format("{0}: {1} -> {2}", OrigProp.Name,
                                                       OrigProp.GetValue(Orig, null),
                                                       DestProp.GetValue(Dest, null)) 
                    : string.Format("{0} {1}{2}: {3} -> {4}", Differences,
                                                              Environment.NewLine,
                                                              OrigProp.Name,
                                                              OrigProp.GetValue(Orig, null),
                                                              DestProp.GetValue(Dest, null));
        }
    }
    return Differences;
}

任何建议或想法表示赞赏吗?

编辑:针对.NET 2.0,因此LINQ毫无疑问。


阅读 381

收藏
2020-05-19

共1个答案

一尘不染

....但是我们如何找到第二个List中的等效类以传递给下面的方法;

这是您的实际问题;您必须至少具有一个不可变的属性,一个ID或类似的名称,才能在两个列表中标识相应的对象。如果您没有这样的属性,您将无法解决问题而不会出错。您可以通过搜索最小或逻辑更改来尝试猜测相应的对象。

如果具有这样的属性,则解决方案将变得非常简单。

Enumerable.Join(
   listA, listB,
   a => a.Id, b => b.Id,
   (a, b) => CompareTwoClass_ReturnDifferences(a, b))

感谢danbruc和Noldorin的反馈。两个列表的长度和顺序相同。所以上面的方法很接近,但是您可以修改此方法以将枚举传递给我上面发布的方法吗?

现在我很困惑……这是什么问题?为什么不只是以下内容?

for (Int32 i = 0; i < Math.Min(listA.Count, listB.Count); i++)
{
    yield return CompareTwoClass_ReturnDifferences(listA[i], listB[i]);
}

如果保证相等的长度,甚至可以忽略Math.Min()调用。


由于委托和使用枚举数而不是使用ICollection,因此Noldorin的实现当然更聪明。

2020-05-19