我想要一些关于如何最好地编写一个通用函数的反馈,这个函数可以比较两个列表.列表包含类对象,我们想迭代一个列表,在第二个列表中查找相同的项目并报告任何差异.
我们已经有了比较类的方法,因此我们需要反馈如何从两个列表中提供方法(如下所示).
例如,假设我们有一个简单的"Employee"类,它有三个属性,Name,ID,Department.我们想报告List和另一个List之间的差异.
注意:
两个列表将始终包含相同数量的项目.  
如上所述,我们有一个泛型方法,我们用它来比较两个类,我们如何结合这个方法来满足列表,即从另一个方法,循环通过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是不可能的.
小智 72
此解决方案生成结果列表,其中包含两个输入列表的所有差异.您可以通过任何属性比较您的对象,在我的示例中它是ID.唯一的限制是列表应该是相同的类型:
var DifferencesList = ListA.Where(x => !ListB.Any(x1 => x1.id == x.id))
            .Union(ListB.Where(x => !ListA.Any(x1 => x1.id == x.id)));
Dan*_*ner 15
....但是我们如何找到第二个List中的等价类来传递给下面的方法;
这是你的实际问题; 你必须至少有一个不可变属性,一个id或类似的东西,以识别两个列表中的相应对象.如果你没有这样的属性,无法解决问题而不会出错.您可以尝试通过搜索最小或逻辑更改来猜测相应的对象.
如果你有这样的属性,解决方案变得非常简单.
Enumerable.Join(
   listA, listB,
   a => a.Id, b => b.Id,
   (a, b) => CompareTwoClass_ReturnDifferences(a, b))
感谢danbruc和Noldorin的反馈.两个列表的长度和长度相同.所以上面的方法很接近,但是你可以修改这个方法来将enum.Current传递给我上面发布的方法吗?
现在我很困惑......那有什么问题?为什么不只是以下?
for (Int32 i = 0; i < Math.Min(listA.Count, listB.Count); i++)
{
    yield return CompareTwoClass_ReturnDifferences(listA[i], listB[i]);
}
如果保证等长,则甚至可以省略Math.Min()调用.
Noldorin的实现当然更聪明,因为委托和使用枚举器而不是使用ICollection.
我想你正在寻找这样的方法:
public static IEnumerable<TResult> CompareSequences<T1, T2, TResult>(IEnumerable<T1> seq1,
    IEnumerable<T2> seq2, Func<T1, T2, TResult> comparer)
{
    var enum1 = seq1.GetEnumerator();
    var enum2 = seq2.GetEnumerator();
    while (enum1.MoveNext() && enum2.MoveNext())
    {
        yield return comparer(enum1.Current, enum2.Current);
    }
}
这是未经测试的,但它应该完成这项工作.请注意,对于此方法特别有用的是它是完全通用的,即它可以采用任意(和不同)类型的两个序列并返回任何类型的对象.
当然,这个解决方案假定您要将第n项seq1与第n项进行比较seq2.如果你想根据特定的属性/比较来匹配两个序列中的元素,那么你将需要执行某种类型的连接操作(如danbruc使用的建议Enumerable.Join.如果这两种方法都不是,请告诉我.我正在追求的,也许我可以提出别的建议.
编辑: 
这是一个如何使用CompareSequences最初发布的比较器函数的方法的示例.
// Prints out to the console all the results returned by the comparer function (CompareTwoClass_ReturnDifferences in this case).
var results = CompareSequences(list1, list2, CompareTwoClass_ReturnDifferences);
int index;    
foreach(var element in results)
{
    Console.WriteLine("{0:#000} {1}", index++, element.ToString());
}
| 归档时间: | 
 | 
| 查看次数: | 100804 次 | 
| 最近记录: |