Сравните два списка различий

Я хотел бы получить некоторые отзывы о том, как лучше всего написать общую функцию, которая позволит сравнивать два списка. Списки содержат объекты classа, и мы хотели бы перебирать один список, ищем один и тот же элемент во втором списке и сообщать о любых различиях.

У нас уже есть метод сравнения classов, поэтому нам нужна обратная связь о том, как мы можем подавать метод (показано ниже) из двух списков.

Например, скажем, у нас есть простой class «Сотрудник», который имеет три свойства: имя, идентификатор, отдел. Мы хотим сообщить о различиях между списком и другим списком.

Заметка:
Оба списка всегда будут содержать одинаковое количество элементов.

Как уже упоминалось выше, у нас есть общий метод, который мы используем для сравнения двух classов, как мы можем включить этот метод для обслуживания списков, т. Е. Из другого метода, через List List и передать classы в общий метод …. но как найти эквивалентный class во втором списке, чтобы перейти к приведенному ниже методу;

public static string CompareTwoClass_ReturnDifferences(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; } 

Любые предложения или идеи оценены?

Edit: Targeting .NET 2.0, поэтому LINQ не может быть и речи.

…. но как найти эквивалентный class во втором списке, чтобы перейти к следующему методу;

Это ваша фактическая проблема; вы должны иметь по крайней мере одно неизменяемое свойство, идентификатор или что-то в этом роде, чтобы идентифицировать соответствующие объекты в обоих списках. Если у вас нет такого имущества, вы не можете решить проблему без ошибок. Вы можете просто попытаться угадать соответствующие объекты, выполнив поиск минимальных или логических изменений.

Если у вас есть такое свойство, решение становится очень простым.

 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 () может даже быть опущен, если гарантирована равная длина.


Внедрение Нолдорина, конечно, разумнее из-за делегата и использования счетчиков вместо использования ICollection.

Это решение создает список результатов, содержащий все отличия от обоих входных списков. Вы можете сравнить свои объекты по любому свойству, в моем примере это идентификатор. Единственное ограничение состоит в том, что списки должны быть одного типа:

 var DifferencesList = ListA.Where(x => !ListB.Any(x1 => x1.id == x.id)) .Union(ListB.Where(x => !ListA.Any(x1 => x1.id == x.id))); 

Я думаю, вы ищете такой метод:

 public static IEnumerable CompareSequences(IEnumerable seq1, IEnumerable seq2, Func 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 с функцией 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()); } 

Этот подход от Microsoft работает очень хорошо и предоставляет возможность сравнить один список с другим и переключить их, чтобы получить разницу в каждом. Если вы сравниваете classы, просто добавляйте свои объекты в два отдельных списка, а затем выполняйте сравнение.

http://msdn.microsoft.com/en-us/library/bb397894.aspx

Надеюсь, что я правильно понимаю ваш вопрос, но вы можете сделать это очень быстро с Linq. Я предполагаю, что универсально вы всегда будете иметь свойство Id. Просто создайте интерфейс, чтобы обеспечить это.

Если вы определяете, что объект будет одним и тем же изменением от classа к classу, я бы рекомендовал передать делегат, который возвращает true, если два объекта имеют одинаковый постоянный идентификатор.

Вот как это сделать в Linq:

 List listA = new List(); List listB = new List(); listA.Add(new Employee() { Id = 1, Name = "Bill" }); listA.Add(new Employee() { Id = 2, Name = "Ted" }); listB.Add(new Employee() { Id = 1, Name = "Bill Sr." }); listB.Add(new Employee() { Id = 3, Name = "Jim" }); var identicalQuery = from employeeA in listA join employeeB in listB on employeeA.Id equals employeeB.Id select new { EmployeeA = employeeA, EmployeeB = employeeB }; foreach (var queryResult in identicalQuery) { Console.WriteLine(queryResult.EmployeeA.Name); Console.WriteLine(queryResult.EmployeeB.Name); } 
  • В чем разница между HashSet и List ?
  • Как я могу получить каждый n-й элемент из списка ?
  • Как присоединиться к двум спискам в Java?
  • Как преобразовать Список в другой список
  • Самый быстрый способ удалить повторяющееся значение из списка лямбдой
  • .NET List Concat vs AddRange
  • Linq выбирает объекты в списке, где существует IN (A, B, C)
  • объединение большого списка объектов xts
  • Преобразование списка кадров данных в один фрейм данных
  • Список против карты в Java
  • Преобразование DataSet в список
  • Давайте будем гением компьютера.